Optimize Create

2020-05-01 06:29发布

问题:

I got 20 000 apples.

How do I create them in a smarter way than this?

        foreach (var a in apples)
        {
            graphClient.Cypher
                .Create("(a:Apple {newApple})")
                .WithParam("newApple", a)
                .ExecuteWithoutResults();
        }

Looking for a generic way to be able to pass objects without specifying each property.

class Fruit
{
    [JsonProperty(PropertyName = "Color")]
    public bool Color { get; set; }
}

class Apple : Fruit
{
    [JsonProperty(PropertyName = "Variety")]
    public String Variety { get; set; }
}

回答1:

I suppose apples is a list of dictionaries. In that case, a more optimized query in plain Cypher would look like this:

UNWIND {apples} AS newApple
CREATE (a:Apple)
SET a = newApple

I have not yet used the Neo4jClient .NET lib, but something along these lines should work:

graphClient.Cypher
    .Unwind(apples, "newApple")
    .Create("(a:Apple)")
    .Set(...)
    .ExecuteWithoutResults();

20k nodes might work in a single transaction, but it's worth to implement some batching and use batches of approx. 10k nodes.

Update. Updated the implementation per Chris Skardon's suggestion.

Remark. In the Cypher query, if you are using Neo4j 3.2+, you should switch to the new parameter syntax, that uses $param style parameters, so the query is slightly easier to read:

UNWIND $apples AS newApple
CREATE (a:Apple)
SET a = newApple