在neo4j中批量插入数据

时间:2015-09-16 12:11:31

标签: neo4j neo4jclient

基于现有的关系表,我想创建一个图表。该表具有以下两列ItemId和ParentItemId。 ParentItemId可以为null。该图表将包含父项和子项之间的项目和“子”关系。为此,我使用了以下代码:

    public class ItemRecord
    {
        public int ItemId;
        public int? ParentItemId;
    }

    public class ItemNode
    {
        public int ItemId;            
    }

    public void BuildGraph(IEnumerable<ItemRecord> data)
    {
        var graphClient = new GraphClient(new Uri("http://localhost:7474/db/data"), "user", "pass");
        graphClient.Connect();

        var tran = graphClient.BeginTransaction();
        var nodes = data.Select(item => new ItemNode {ItemId = item.ItemId});

        try
        {
            //creates the nodes in a single operation
            graphClient.Cypher
            .Create("(n:Item {nodes})")
            .WithParam("nodes", nodes)
            .ExecuteWithoutResults();

            ///creates the relations
            foreach (var nodeItem in data)
            {
                if (!nodeItem.ParentItemId.HasValue)
                {
                    continue;
                }
                graphClient.Cypher
                    .Match("(source:Item)", "(destination:Item)")
                    .Where((ItemNode source) => source.ItemId == nodeItem.ParentItemId.Value)
                    .AndWhere((ItemNode destination) => destination.ItemId == nodeItem.ItemId)
                    .Create("source-[:Parent]->destination")
                    .ExecuteWithoutResults();
            }
            tran.Commit();
        }
        catch (Exception)
        {                
            tran.Rollback();
        }                        
    }

首先,我创建节点,然后创建它们之间的关系。这种方法很慢。对于1000件物品大约需要。 10秒问题是我为每个关系调用neo4j服务器。有没有办法在单个语句中创建图形?我怎样才能提高性能?

2 个答案:

答案 0 :(得分:2)

TL; DR; - import tool example

您可以使用Neo4j服务器提供的import tool。它能够非常快速地导入大量数据。

工具接受输入的CSV文件。所以,你应该做的是:

1)编写将所有数据处理成CSV文件并将其保存到磁盘上的脚本(或类似内容) 2)使用导入工具并将准备好的CSV文件导入数据库。

注意:在此过程中不会创建索引。稍后应使用标准的Neo4j功能添加它们。

示例:

<强> nodes.csv

ItemId:ID,:LABEL,value
item1,Item,"some"
item2,Item,"other"
item3,Item,"another"

<强> relationships.csv

:START_ID,:END_ID,:TYPE
item1,item2,Parent
item1,item3,Parent

并命令:

neo4j-import --into path_to_target_directory --nodes nodes.csv --relationships relationships.csv

答案 1 :(得分:0)

您是否尝试过使用UNWIND

我有以下内容,它在大约4秒钟内创建100,000个节点(或者在300毫秒内创建1,000个节点)。显然我不得不假装&#39;一些ItemRecord个实例,因此它可能不完全相同 - 并且需要在您的ItemId属性上设置索引。

以下代码应该只是当前方法中的复制/替换:

public void BuildGraph(IEnumerable<ItemRecord> data)
{
    var graphClient = new GraphClient(new Uri("http://localhost:7474/db/data"), "user", "pass");
    graphClient.Connect();

    //Create the Index.
    graphClient.Create("INDEX ON :Item(ItemId)").ExecuteWithoutResults();

    var tran = graphClient.BeginTransaction();
    var nodes = data.Select(item => new ItemNode {ItemId = item.ItemId});

    try
    {
        //creates the nodes in a single operation
        graphClient.Cypher
            .Create("(n:Item {nodes})")
            .WithParam("nodes", nodes)
            .ExecuteWithoutResults();

        var nodesWithParents = data.Where(n => n.ParentItemId.HasValue);

        //creates the relations
        graphClient.Cypher
            .Unwind(nodesWithParents, "node")
            .Match("(source:Item {ItemId: node.ItemId}),(destination:Item {ItemId : node.ParentItemId})")
            .Create("source-[:Parent]->destination")
            .ExecuteWithoutResults();

        tran.Commit();
    }
    catch (Exception)
    {                
        tran.Rollback();
    }                        
}