Search code examples
neo4jneo4jclient

Creating New Nodes and Adding Relationships to Existing


I have a small graph, it has 'Parent' nodes (as in Nodes that define the parent of a child) and 'Child' Nodes (the children of said parents). I have noticed a small problem in the way I create siblings of existing children, and was hoping for some pointers.

return client.Cypher
            .Match("(person:Person),(c:IdCounter)")
            .Where((Person person) => person.Email == '[email protected]')
            .Create("person-[:PARENT_OF]->(child:Child {name:'fred',dob:timestamp()})")
            .Set("child.timestamp = timestamp()")
            .Set("child.id = c.nextId")
            .Set("c.nextId = c.nextId + 1")
            .Return<Child>("child").Results.ToList();

This creates a child that has a parent and creates the relationship, this works perfectly, well, as it was designed to. This next bit however is where I have a problem:

return client.Cypher
            .Match("(child:Child)<-[:PARENT_OF]-(person:Person),(c:IdCounter)")
            .Where((Person person) => person.Email == '[email protected]')
            .Create("(child2:Child {name:'derf',dob:timestamp()})")
            .Set("child2.id = c.nextId")
            .Set("c.nextId = c.nextId + 1")
            .Create("(person)-[:PARENT_OF]->(child2)")
            .Create("(child2)-[:SIBLING_OF]->(child)")
            .Return<Child>("child2").Results.ToList();

Now the first time I run this sibling code I get a second child, linked to the parent, and linked to its sibling, so for most cases this would be fine, but I have 4 children :/

The second time I run the sibling code I get 2 children created (the same child twice with consecutive id's), and they are linked to the parent (PARENT_OF), but 1 new child links to 1 existing child (SIBLING_OF) and the second new child links to the other existing child (SIBLING_OF). EDIT: This is the Cypher used and the resulting graph after running the sibling code twice: http://ec2-52-89-85-67.us-west-2.compute.amazonaws.com/imagedata/capture.png
I would expect 1 new child to be created, and a SIBLING_OF relationship to be created to the children collected in the original match statement, but that is not what I am getting.

Thanks


Solution

  • This should get you going:

    client.Cypher
        .Match("(c:IdCounter)")
        .Create("(child2:Child {name:'derf',dob:timestamp()})")
        .Set("child2.id = c.nextId")
        .Set("c.nextId = c.nextId + 1")
        .With("child2")
        .Match("(child:Child)<-[:PARENT_OF]-(person:Person)")
        .Where((Person person) => person.Email == "[email protected]")
        .CreateUnique("(person)-[:PARENT_OF]->(child2)")
        .CreateUnique("(child2)-[:SIBLING_OF]->(child)")
        .Return<Child>("DISTINCT child2");
    

    Or at least it creates what I think is what you're after - all the children linked together, and the parent one rel per child.