Neo4J multiple unwinds unexpected behavior

142 Views Asked by At

I am trying to execute the following Neo4J query.

CREATE (c:Content)
WITH c
UNWIND $resources as resource
    MATCH (p:Person {userId: resource["userId"]})
    CREATE (r:Resource)
    CREATE (p)-[:CREATES]->(r)
    CREATE (c)-[:CONTAINS]->(r)
WITH c
UNWIND $tags as tag
    MATCH (t:Tag {name: tag})
    CREATE (c)-[:IS]->(t)
WITH c
UNWIND $goalCategories as category
    MATCH (atc:ATCategory {name: category})
    CREATE (c)-[:IS]->(atc)

$resources is an object list and $tags and $categories are list of strings. I have left the data manipulation part for simplicity.

When this query executes, it creates multiple relationships between c and atc which means that it repeats the category for each item in the tags. To my knowledge, since c is singular, the WITH c block should close the previous unwind but this does not happen. What's weird is that, this does not happen for the resources unwind.

Shortly, the code threats like the UNWIND $goalCategories as category is inside the UNWIND $tags as tag part. If the same happened between UNWIND $resources as resource and UNWIND $tags as tag, it would make sense, but I couldn't figure out why this is only happening for the latter part and not the prior part.

I would really appreciate the help.

Btw: I am executing the code with neo4j-driver on nodejs.

1

There are 1 best solutions below

0
On BEST ANSWER

Running multiple consecutive UNWIND statements will lead to cartesian products. Essentially, all the nested UNWIND will be executed x times, where the x is the number of rows from the previous unwind. The WITH c does not close the previous UNWIND statement, you need to add any aggregation function. For example, you could use the count() aggregation function to effectively reduce the count of rows in between consecutive UNWIND statements to 1 (or close a previous UNWIND as you state).

CREATE (c:Content)
WITH c
UNWIND $resources as resource
    MATCH (p:Person {userId: resource["userId"]})
    CREATE (r:Resource)
    CREATE (p)-[:CREATES]->(r)
    CREATE (c)-[:CONTAINS]->(r)
WITH c, count(*) as dummy
UNWIND $tags as tag
    MATCH (t:Tag {name: tag})
    CREATE (c)-[:IS]->(t)
WITH c, count(*) AS dummy
UNWIND $goalCategories as category
    MATCH (atc:ATCategory {name: category})
    CREATE (c)-[:IS]->(atc)