代码之家  ›  专栏  ›  技术社区  ›  GreyCloud

Neo4j的c#类图

  •  1
  • GreyCloud  · 技术社区  · 7 年前

    (类类型是节点类型并派生自,节点有一个“linkedTo”列表)

    例如,我可以将它们序列化为json,然后直接导入neo4j吗? 我知道C#neo4j驱动程序中的.unwind函数在这里可能有帮助,但看不到它的使用示例,因此需要单独匹配和创建关系

    1 回复  |  直到 7 年前
        1
  •  2
  •   Charlotte Skardon    7 年前

    好的,首先,我使用Neo4jClient来实现这一点,我添加了一个 INDEX 数据库使用:

    CREATE INDEX ON :MyClass(Id)
    

    这对于这种工作方式很重要,因为这样可以更快地插入数据。

    public class MyClass
    {
        public int Id {get;set;}
        public string AValue {get;set;}
        public ICollection<int> LinkToIds {get;set;} = new List<int>();
    }
    

    它有一个 Id 我会把它关掉,然后 string LinkToIds 属性是此实例链接到的ID的集合。

    生成我的 MyClass 我使用此方法随机生成的实例:

    private static ICollection<MyClass> GenerateMyClass(int number = 50000){
        var output = new List<MyClass>();
    
        Random r = new Random((int) DateTime.Now.Ticks);
    
        for (int i = 0; i < number; i++)
        {
            var mc = new MyClass { Id = i, AValue = $"Value_{i}" };
            var numberOfLinks = r.Next(1, 10);  
            for(int j = 0; j < numberOfLinks; j++){
                var link = r.Next(0, number-1);
                if(!mc.LinkToIds.Contains(link) && link != mc.Id)
                    mc.LinkToIds.Add(link);
            }
            output.Add(mc);
        }
    
        return output;
    }
    

    然后我用另一种方法把它分成更小的“批”:

    private static ICollection<ICollection<MyClass>> GetBatches(ICollection<MyClass> toBatch, int sizeOfBatch)
    {
        var output = new List<ICollection<MyClass>>();
    
        if(sizeOfBatch > toBatch.Count) sizeOfBatch = toBatch.Count;
    
        var numBatches = toBatch.Count / sizeOfBatch;
        for(int i = 0; i < numBatches; i++){
            output.Add(toBatch.Skip(i * sizeOfBatch).Take(sizeOfBatch).ToList());
        }
    
        return output;
    }
    

    然后要实际添加到数据库中:

    void Main()
    {
        var gc = new GraphClient(new Uri("http://localhost:7474/db/data"), "neo4j", "neo");
        gc.Connect();
    
        var batches = GetBatches(GenerateMyClass(), 5000);
    
        var now = DateTime.Now;
        foreach (var batch in batches)
        {
            DateTime bstart = DateTime.Now;
            var query = gc.Cypher
                .Unwind(batch, "node")
                .Merge($"(n:{nameof(MyClass)} {{Id: node.Id}})")
                .Set("n = node")
                .With("n, node")
                .Unwind("node.LinkToIds", "linkTo")
                .Merge($"(n1:{nameof(MyClass)} {{Id: linkTo}})")
                .With("n, n1")
                .Merge("(n)-[:LINKED_TO]->(n1)");
    
            query.ExecuteWithoutResults();
            Console.WriteLine($"Batch took: {(DateTime.Now - bstart).TotalMilliseconds} ms");
        }
        Console.WriteLine($"Total took: {(DateTime.Now - now).TotalMilliseconds} ms");
    }
    

    在我老化的机器上(现在已经5-6岁了),大约需要20秒才能放入50000个节点,大约需要500000个关系。

    UNWIND -在这里我 展开 node . 然后我可以访问属性( node.Id MERGE 一个节点。在第一次放松的时候-我总是 SET 新创建的节点( n 节点 AValue )准备好了。

    所以直到第一次 With 我们创建了一个新节点 标签,以及它的所有属性集。现在。这包括 如果你是一个整洁的人-你可能想删除。我把那留给你自己。

    在第二个 展开 我们利用这个事实 属性是一个数组,并使用它创建一个稍后将填充的“占位符”节点,然后在 n个 以及 n1 n1型 我们将使用该节点,当我们在第一个 展开 我们将设置占位符的所有属性。

    合并 在Neo4j文档中。