Neo4j: Creating nodes and relationships from a list of maps
Last week Alistair and I were porting some Neo4j cypher queries from 1.8 to 2.0 and one of the queries we had to change was an interesting one that created a bunch of relationships from a list/array of maps.
In the query we had a user 'Mark' and wanted to create 'FRIENDS_WITH' relationships to Peter and Michael.
The application passed in a list of maps representing Peter and Michael as a parameter but if we remove the parameters the query looked like this:
MERGE (me:User {userId: 1} )
SET me.name = "Mark"
FOREACH (f IN [{userId: 2, name: "Michael"}, {userId: 3, name: "Peter"}] |
MERGE (u:User {userId: f.userId})
SET u = f
MERGE (me)-[:FRIENDS_WITH]->(u))
We first ensure that a user with 'id' of 1 exists in the database and then make sure their name is set to 'Mark'. After we’ve done that we iterate over a list of maps containing Mark’s friends and ensure there is a 'FRIENDS_WITH' relationship from Mark to them.
The parameterised version of that query looks like this:
MERGE (me:User { userId: {userId} })
SET me.name = {name}
FOREACH(f IN {friends} |
MERGE (u:User {userId: f.userId })
SET u = f
MERGE (me)-[:FRIENDS_WITH]->(u))
We can then execute that query using Jersey:
public class ListsOfMapsCypher
{
public static void main( String[] args )
{
ObjectNode request = JsonNodeFactory.instance.objectNode();
request.put("query",
"MERGE (me:User { userId: {userId} }) " +
"SET me.name = {name} " +
"FOREACH(f IN {friends} | " +
"MERGE (u:User {userId: f.userId }) " +
"SET u = f " +
"MERGE (me)-[:FRIENDS_WITH]->(u)) ");
ObjectNode params = JsonNodeFactory.instance.objectNode();
params.put("userId", 1);
params.put("name", "Mark");
ArrayNode friends = JsonNodeFactory.instance.arrayNode();
ObjectNode friend1 = JsonNodeFactory.instance.objectNode();
friend1.put( "userId", 2 );
friend1.put( "name", "Michael" );
friends.add( friend1 );
ObjectNode friend2 = JsonNodeFactory.instance.objectNode();
friend2.put( "userId", 3 );
friend2.put( "name", "Peter" );
friends.add( friend2 );
params.put("friends", friends );
request.put("params", params );
ClientResponse clientResponse = client()
.resource( "http://localhost:7474/db/data/cypher" )
.accept( MediaType.APPLICATION_JSON )
.entity( request, MediaType.APPLICATION_JSON_TYPE )
.post( ClientResponse.class );
System.out.println(clientResponse.getEntity( String.class ));
}
private static Client client()
{
DefaultClientConfig defaultClientConfig = new DefaultClientConfig();
defaultClientConfig.getClasses().add(JacksonJsonProvider.class);
return Client.create(defaultClientConfig);
}
}
We can then write a query to check Mark and his friends were persisted:
And that’s it!
About the author
I'm currently working on short form content at ClickHouse. I publish short 5 minute videos showing how to solve data problems on YouTube @LearnDataWithMark. I previously worked on graph analytics at Neo4j, where I also co-authored the O'Reilly Graph Algorithms Book with Amy Hodler.