6

I have many nodes and edges in a list. Currently I'm looping through the list and inserting each node with a query which is very slow. How do I perform a batch insert using neo4jclient?

Node object:

public class myNode
{
    public int id { get; set; }
    public int floor { get; set; }
    public double x { get; set; }
    public double y { get; set; }
}

Current method for inserting a node:

public static void addNode(GraphClient client, myNode node, string nodeName)
{
    client.Cypher
       .Create("(" + nodeName + ":Node {node})")
       .WithParams(new { node })
       .ExecuteWithoutResults();
}

Current method for inserting List of nodes:

List<myNode> nodeList;
foreach(var elem in nodeList)
    addNode(client, elem, "foo");
Nitin Labhishetty
  • 1,290
  • 2
  • 21
  • 41
  • similar question with other answer here: https://stackoverflow.com/q/47360571/237509 – JOG Jan 03 '18 at 23:29

2 Answers2

5

Instead of just passing a single node into your Cypher, you could pass in the collection. According to the Neo4j manual

By providing Cypher an array of maps, it will create a node for each map

See the section Create multiple nodes with a parameter for their properties in the Neo4j Manual v2.2.2.

Therefore your C# code will become simplified and should perform better.

public static void AddNodes(GraphClient client, List<MyNode> nodes)
{
    client.Cypher
       .Create("(n:Node {nodes})")
       .WithParams(new { nodes })
       .ExecuteWithoutResults();
}

Hope that helps.

ceej
  • 1,863
  • 1
  • 15
  • 24
  • I tried this out of curiosity just after posting the question and it to my surprise, it worked! Good to know that this is the solution. There is one issue though, I'm unable to figure out how to add a batch of relationships between these node after this. I constructed the query string for adding all nodes and relationships at once but it sort of defeats many purposes of using an ORM. – Nitin Labhishetty Jun 17 '15 at 11:22
  • @codeln glad you got to the same solution. Would it be OK to ask if you could mark as an answer to make it clear to others? As to your other issue - I would start another question with some more detail. If I can help I will. – ceej Jun 17 '15 at 13:34
  • :D sure, thanks for the help. Please do get back to me if you find a solution for the relationships (the question does ask for batch insert of nodes AND RELATIONS) – Nitin Labhishetty Jun 17 '15 at 14:12
2

For completeness the following is an example that can be adapted to bulk load relationships and their properties using neo4jclient.

public void CreateRelationships(List<RelationshipCommon> relationships)
{
            graphClient.Cypher
            .Unwind(relationships, "relationship")
            .Match("(grant:GRANT)", "(target:THEME)")
            .Where("grant.node_id = relationship.SourceEntityId and target.node_id = relationship.TargetEntityId")
            .Create("grant-[r:IS_IN_THEME]->target")
            .Set("r.relationship_id = relationship.RelationshipId")
            .Set("r.grant_proportional_value = relationship.ProportionalValue")
            .ExecuteWithoutResults();
}

The relationships are a List collection of type RelationshipCommon. RelationshipCommon has the following structure

    public class RelationshipCommon
{
    public string SourceEntityId { get; set; }
    public string TargetEntityId { get; set; }
    public string RelationshipId { get; set; }
    public long ProportionalValue { get; set; }
}

On my development VM this code loaded 54000 relationships in 6s.