Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create association between nodes if one doesnt exist using cypher

Tags:

neo4j

cypher

Say there are 2 labels P and M. M has nodes with names M1,M2,M3..M10. I need to associate 50 nodes of P with each Node of M. Also no node of label P should have 2 association with node of M.

This is the cypher query I could come up with, but doesn't seem to work.

MATCH (u:P), (r:M{Name:'M1'}),(s:M) 
where not (s)-[:OWNS]->(u) 
with u limit 50 
CREATE (r)-[:OWNS]->(u);

This way I would run for all 10 nodes of M. Any help in correcting the query is appreciated.

like image 634
Amarendra Reddy Avatar asked Mar 07 '17 07:03

Amarendra Reddy


2 Answers

You can utilize apoc.periodic.* library for batching. More info in documentation

call apoc.periodic.commit("
MATCH (u:P), (r:M{Name:'M1'}),(s:M) where not (s)-[:OWNS]->(u) 
with u,r limit {limit}
CREATE (r)-[:OWNS]->(u)
RETURN count(*)
",{limit:10000})

If there will always be just one (r)-[:OWNS]->(u) relationship, I would change my first match to include

call apoc.periodic.commit("
MATCH (u:P), (r:M{Name:'M1'}),(s:M) where not (s)-[:OWNS]->(u) and not (r)-[:OWNS]->(u)
with u,r limit {limit}
CREATE (r)-[:OWNS]->(u)
RETURN count(*)
",{limit:10000})

So there is no way the procedure will fall into a loop

like image 137
Tomaž Bratanič Avatar answered Oct 02 '22 07:10

Tomaž Bratanič


This query should be a fast and easy-to-understand. It is fast because it avoids Cartesian products:

MATCH (u:P)
WHERE not (:M)-[:OWNS]->(u) 
WITH u LIMIT 50
MATCH (r:M {Name:'M1'})
CREATE (r)-[:OWNS]->(u);

It first matches 50 unowned P nodes. It then finds the M node that is supposed to be the "owner", and creates an OWNS relationship between it and each of the 50 P nodes.

To make this query even faster, you can first create an index on :M(Name) so that the owning M node can be found quickly (without scanning all M nodes):

CREATE INDEX ON :M(Name);
like image 37
cybersam Avatar answered Oct 02 '22 07:10

cybersam