Search code examples
neo4jcypherneo4j-apocopencypher

Neo4j, empty list in first unwind stop second unwind from executing


I have two unwinds, that create some relationships and nodes, but if the list for the first unwinds is empty, the second unwind doesn't execute.

How can I fix that?

CALL apoc.periodic.iterate(
    "
        UNWIND $POSTS as post
        RETURN post
    ",
    "
        MERGE (p:Post{id: post.id})

        WITH p, post
        UNWIND post.tags as value
        MERGE (t:Tag{tag: value})
        MERGE (t)-[:has_tag]->(p)

        WITH p, post
        UNWIND post.user_mentions as user_mention
        MERGE (u1:User{id: user_mention})
        MERGE (p)-[:mentions]->(u1)
    ",
    {batchSize: 500, params: {POSTS: $POSTS}, iterateList:true}
)

Example results

Parameters, with non-empty tags

[
    {
        "id": 123,
        "tags": [1],
        "user_mentions": [123, 234],
    }
]

Graph created in database - Expected result

enter image description here

Parameters, with empty tags

[
    {
        "id": 123,
        "tags": [],
        "user_mentions": [123, 234],
    }
]

Graph created in the database (Lacking 'mentions' relationships) - Unexpected result

enter image description here


Solution

  • This is expected, UNWIND produces rows and thus if the list is empty no rows are produced and the query doesn't continue.

    You need to switch to FOREACH for this use case :

    CALL apoc.periodic.iterate(
        "
            UNWIND $POSTS as post
            RETURN post
        ",
        "
            MERGE (p:Post{id: post.id})
            WITH p, post
            FOREACH(value IN  post.tags |
              MERGE (t:Tag{tag: value})
              MERGE (t)-[:has_tag]->(p)
            )
            WITH p, post
            FOREACH(user_mention IN post.user_mentions |
              MERGE (u1:User{id: user_mention})
              MERGE (p)-[:mentions]->(u1)
            )
        ",
        {batchSize: 500, params: {POSTS: $POSTS}, iterateList:true}
    )