Neo4j's Cypher : create 1-to-n relationships only when populating database
-
21-12-2019 - |
Question
I recently tried to populate a neo4j test database using this code :
WITH ["Paul","Graham","Voord","Heisenberg","Earles","Grey","Herzog","Griffith","Rogers","Huxley","Waldorf","Astor","Mellon","Humphrey","Messerschmidt","Carmichael","Buchanan","Dalton","Valentino","Meyerholz","Ellington","Abernathy","Harrington","Monroe","Rutherford","Vanderbilt","Montgomery","Worthington","Fitzwilliam","Covington","Hollingsworth"]
AS names,
["Associates",""]
AS suffixes
FOREACH (r IN range(0,49) | CREATE (:Societe {id:10000+r, name:names[r % size(names)]+" & "+names[(r+3) % size(names)]+" "+suffixes[r % size(suffixes)]}));
FOREACH (r IN range(0,99) | CREATE (:Dossier {id:20000+r, Numero:"0"+(r*4)+100}));
MATCH (s:Societe),(d:Dossier)
WITH s,d
WHERE rand() < 0.1
CREATE (s)-[:CONTAINS]->(d);
But, as you may have guessed, the four last lines create n-to-n relationships between my (:Dossiers) and my (:Societes). What i initially wanted was to create a 1-to-n relationship between these, so that a (:Dossier) can be linked to one (:Societe) at most.
Any idea how to accomplish this ?
Thanks.
Solution
Nicolas,
Here's a bit of Cypher to replace your last 4 lines that may get you where you want to go.
MATCH (s:Societe)
WITH s
MATCH (d:Dossier)
WHERE NOT (d)<-[:CONTAINS]-() AND RAND() < 0.1
CREATE (s)-[:CONTAINS]->(d);
MATCH (d:Dossier)-[r:CONTAINS]-()
WITH d, collect(r) AS rels1
WITH d, rels1[1..] AS rels2
FOREACH(q IN rels2 | DELETE q)
The first part reduces the number of interconnections, but doesn't make 1-to-n (which confuses me, but that's the way it goes). The second part trims the relationships so that each dossier is associated with 1 societe. You will likely have dossiers that have no assignment to a societe, but you can find and remove those.
Grace and peace,
Jim
OTHER TIPS
You can filter out the dossier that already have a societe.
MATCH (s:Societe), (d:Dossier)
WITH s,d
WHERE rand() < 0.1 and NOT (s)-[:CONTAINS]->()
CREATE (s)-[:CONTAINS]->(d);