Search code examples
neo4jcypher

neo4j: cypher if else


I have 3 type of nodes: FOLDER, TYPE_A, TYPE_B and one relationship: CONTAINS;

I am having difficulty in writing cypher, in a single query, to fetch this:

if(folder CONTAINS TYPE_A) {
   return ids of TYPE_A
} else if (folder CONTAINS TYPE_B) {
  then return ids of TYPE_B
} else {
  return empty array;
}

Can someone help?


Solution

  • One way is to use apoc.do.when to fetch the ids of TYPE_B conditionally, when no TYPE_A nodes are present. Like this:

    MATCH (n:FOLDER)
    OPTIONAL MATCH (n)-[:CONTAINS]-(m:TYPE_A)
    WITH n, collect(id(m)) AS typeAIds
    CALL apoc.do.when(
       size(typeAIds) = 0, 
       'OPTIONAL MATCH (n)-[:CONTAINS]-(m:TYPE_B) WITH n, collect(id(m)) AS typeBIds RETURN typeBIds', 
       'RETURN [] as typeBIds', 
       {n: n}
    ) 
    YIELD value
    RETURN n, typeAIds + value.typeBIds AS ids
    

    In this query, we first fetch the TYPE_A node ids and collect them in an array. If those ids are not present, then we fetch TYPE_B node ids, within apoc.do.when. Finally, we return the output. This is a bit more optimized as we only fetch the relationships if needed. You will need to install, APOC library for this query to work. Another variant of the same query is this:

    MATCH (n:FOLDER)
    CALL apoc.do.when(
        SIZE([(n)-[:CONTAINS]-(:TYPE_A) | 1]) <> 0, 
        'OPTIONAL MATCH (n)-[:CONTAINS]-(m:TYPE_A) WITH n, collect(id(m)) AS typeAIds RETURN typeAIds', 
        'RETURN [] as typeAIds', 
        {n: n}
    )
    YIELD value AS v1
    CALL apoc.do.when(
        SIZE([(n)-[:CONTAINS]-(:TYPE_B) | 1]) <> 0 AND SIZE(v1.typeAIds) = 0, 
        'OPTIONAL MATCH (n)-[:CONTAINS]-(m:TYPE_B) WITH n, collect(id(m)) AS typeBIds RETURN typeBIds', 
        'RETURN [] as typeBIds', 
        {n: n}
    )
    YIELD value AS v2
    RETURN n, v1.typeAIds + v2.typeBIds AS ids