neo4jcypher

Query to return nodes with incoming edges but exclude nodes that also have outgoing edges of the same edge type


I have a database formatted like this:

(a:Concept)-[r:BROADER_TERM]->(b:Concept)-[s:BROADER_TERM]->(c:Concept)-[t:RELATED_TERM]->(d:Concept)

I'd like to write a query that returns Concept nodes that only have incoming BROADER_TERM edges and excludes any node that has both incoming and outgoing BROADER_TERM edges (ie I want to return the 'broadest term'). In the example above, it would be a query that only returns node c.

I tried something like this:

MATCH (a:Concept)-[r:BROADER_TERM]->(b)
WHERE NOT (b)-[r]->(c:Concept)
RETURN b

But I can't introduce a new variable in the WHERE NOT clause.

Can someone show me the correct syntax for this type of query?


Solution

  • This query will find all the "broadest" concepts (i.e., Concept nodes that have no broader concepts):

    MATCH (c:Concept)
    WHERE NOT (c)-[:BROADER_TERM]->()
    RETURN c
    

    But if you really want to show the "broadest" concepts that have at least one "lesser" concept:

    MATCH (c:Concept)
    WHERE NOT (c)-[:BROADER_TERM]->() AND ()-[:BROADER_TERM]->(c)
    RETURN c
    

    Note: NOT has higher precedence than AND, so the NOT above only applies to (c)-[:BROADER_TERM]->().