I'm currently writing a mongoose plugin to maintain neo4j nodes automatically using the javascript neo4j driver and currently working on mapping updates (the saving part works atm) to a cypher query.
I'm currently stuck at the use case where I want to update multiple relationships between the document (a :Class
, saved as node in neo4j) and the updated references (students of type :Person
, saved as different nodes in neo4j) while deleting the old relationships tied to the old references (students in this case). This is a result of updating an array of subdocument references in neo4j.
The main problem, besides the cross (cartesian) product that is created in the query, is that the following query creates twice as much relationships as it deletes:
MATCH (doc:Class {m_id: '5bf5b9df11c344021de89395'}),
(I:Person {m_id: '5bf5b9df11c344021de89393'}),
(II:Person {m_id: '5bf5b9df11c344021de89394'}),
(:Class {m_id: '5bf5b9df11c344021de89395'})-[r]->()
WHERE type(r) IN ["HAS_STUDENT"]
CREATE (doc)-[:HAS_STUDENT]->(I), (doc)-[:HAS_STUDENT]->(II)
DELETE r;
This removes 2 relationships (which is correct), but creates 4 new relationships (should be 2).
Also using a single CREATE
in the form of CREATE (I)<-[:HAS_STUDENT]-(doc)-[:HAS_STUDENT]->(II)
is not a valid option as this query is created in a for loop and can have an increasing amount of new relationships to be created. (Also the main reason why I want to optimize the query.)
I've had multiple versions of this query which all resulted in the same output. The problem is probably in the WHERE
part, because when I use the query below it creates the right amount of relationships. The only missing thing is that it should only delete the old relationships:
MATCH (doc:Class {m_id: '5bf5b9df11c344021de89395'}),
(I:Person {m_id: '5bf5b9df11c344021de89393'}),
(II:Person {m_id: '5bf5b9df11c344021de89394'})
CREATE (doc)-[:HAS_STUDENT]->(I), (doc)-[:HAS_STUDENT]->(II)
WITH doc
MATCH (doc)-[r]->(n)
WHERE type(r) IN ["HAS_STUDENT"]
DELETE r;
So my main question, besides resolving the problem, is how to efficiently write this query for the described behavior. I use the neo4j driver, so I have availability of using parameters.
NOTE: I and II will later be used as variables to assign unique relationships values, that's why I haven't used a single MATCH
for the :Person
nodes.
Also, the IN
of the relationshiptype in the WHERE
clause is used because of the possibility of different types of relationships to be created (and thus the old ones of that type deleted).
At last, I already have looked into UNWIND
and FOREACH
but can't seem to fit these into the described usecase.