簡體   English   中英

c#類圖到Neo4j

[英]c# class graph to Neo4j

我希望將內存中的普通C#類轉換為neo4j數據庫。 (類類型是節點類型,並且是從節點派生的,節點具有“ linkedTo”的列表)

我想知道是否還有其他更聰明的方法,而不是編寫一系列的密碼查詢來創建節點和屬性,然后將它們與關系鏈接起來。

例如,我可以將它們序列化為json,然后將其直接導入neo4j嗎? 我知道C#neo4j驅動程序中的.unwind函數在這里可能會有所幫助,但看不到其用法的好示例,因此需要分別匹配和創建關系

是否有執行此操作的最佳方法? 我預計大約有5萬個節點

好的,首先,我正在為此使用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歲)上,大約需要50秒才能放置50,000個節點以及大約500,000個關系。

讓我們進入上面對Neo4j的重要調用。 關鍵的事情就是您正確建議的UNWIND我在這里UNWIND一批,並為該集合中的每個“行”指定node的標識符。 然后我可以訪問屬性( node.Id )並用它來MERGE的節點。 在第一開卷-我總是SET新創建的節點( n )是node ,因此所有的屬性(本例中僅有AValue )設置。

因此,直到第一個With我們都創建了一個帶有MyClass標簽的新Node,並設置了其所有屬性。 現在。 這確實包括擁有一個LinkToIds數組,如果您是一個整潔的人,則可能希望將其刪除。 我會留給自己。

在第二個UNWIND我們利用LinkToIds屬性是一個數組這一事實,並使用它來創建一個“占位符”節點,該節點將在以后填充,然后在nn1占位符之間創建一個關系。 注意:如果我們已經創建了一個與n1相同的ID的節點,我們將使用該節點,並且在第一個UNWIND期間獲得相同的ID時,將設置占位符的所有屬性。

這不是最簡單的解釋,但是最好看的是Neo4j文檔中的MERGEUNWIND

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM