Search code examples
neo4jcypher

Neo4 cypher: Check if node with relationships to a list of node IDs exists


I have the following node structure: (:Patch)-[:INCLUDES]->(:Roster)-[:HAS]->(:PublicList)-[:INCLUDES]->(u:Unit)

Then I have an array of :Unit ids: [197, 196, 19, 20, 191, 171, 3, 174, 194, 185]

I would like to check whether a :PublicList that has the :INCLUDES relationship to all the :Unit ids in the list already exists.

I tried writing a COUNT and MATCH query like this, but this just seems like an error-prone long-winded approach:

MATCH (p:Patch)-[:INCLUDES]->(r:Roster)-[:HAS]-(d:PublicList)
    WITH COLLECT(d) as drafts
    UNWIND drafts as draft
    WITH draft
    UNWIND [197, 196, 19, 20, 191, 171, 3, 174, 194, 185] as unitID
      MATCH (draft)-[:INCLUDES]->(u:Unit)
      WHERE id(u) = unitID
      WITH count(DISTINCT u) as draftUnits
    WITH COLLECT(draftUnits) as matchCounts
    RETURN matchCounts

Can someone help me write this so it returns a boolean if a :PublicList has a:INCLUDES relationship to all the IDs in the list?


Solution

  • I suggest to first match the units, put them into a collection and then use the ALL predicate to check that the PublicList has a connection to all units.

    MATCH (n:Unit) WHERE id(n) IN [197, 196, 19, 20, 191, 171, 3, 174, 194, 185]
    WITH collect(n) AS units
    MATCH (p:Patch)-[:INCLUDES]->(r:Roster)-[:HAS]-(d:PublicList)
    WHERE ALL(x IN units WHERE (d)-[:INCLUDES]->(x))
    RETURN count(*) AS matchCount
    

    If you want to return the PublicList along with a boolean value if it matches all of them, you can slightly adjust like this

    MATCH (n:Unit) WHERE id(n) IN [197, 196, 19, 20, 191, 171, 3, 174, 194, 185]
    WITH collect(n) AS units
    MATCH (p:Patch)-[:INCLUDES]->(r:Roster)-[:HAS]-(d:PublicList)
    RETURN d, ALL(x IN units WHERE (d)-[:INCLUDES]->(x)) as matchAll