cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

RETURN matching nodes and non-matching nodes

JB47394
Node Link

In a single query, how can I return both nodes that match an expression as well as nodes that don't match that expression?

The specific situation I'm in is that I want two sets of nodes returned; one with a relationship and one without that relationship. Note that the nodes without the relationship get deleted in the query - but I want their id() values anyway.

Right now I have a query that does all the work I need, and returns the nodes without the relationship, but adding in a return of the nodes with the relationship has eluded me. I hesitate to include the query because it's pretty complex. I'm hoping that being told how to conceptually do this will give me enough information to solve my problem.

1 ACCEPTED SOLUTION

You'll have to start with a MATCH on all of them and then use an approach which lets you only deleted the elements you want while not filtering out the set. Maybe something like this?

MATCH (n:Node)
WITH n, exists((n)-[:REL]-()) as hasRel
FOREACH (x in CASE WHEN hasRel THEN [] ELSE [n] END | 
  DETACH DELETE x)
RETURN id(n), hasRel

The idea behind this is that the Cypher within FOREACH executes per element of a list, so we use a CASE to generate the list to operate over. If the relationship exists on the node, then it's an empty list and nothing gets executed by the FOREACH. If no relationship exists on the node, then it will execute on a single-element list, detaching and deleting the node (but not filtering it out).

If using 4.1, you can use subqueries instead for conditional cypher execution:

View solution in original post

2 REPLIES 2

You'll have to start with a MATCH on all of them and then use an approach which lets you only deleted the elements you want while not filtering out the set. Maybe something like this?

MATCH (n:Node)
WITH n, exists((n)-[:REL]-()) as hasRel
FOREACH (x in CASE WHEN hasRel THEN [] ELSE [n] END | 
  DETACH DELETE x)
RETURN id(n), hasRel

The idea behind this is that the Cypher within FOREACH executes per element of a list, so we use a CASE to generate the list to operate over. If the relationship exists on the node, then it's an empty list and nothing gets executed by the FOREACH. If no relationship exists on the node, then it will execute on a single-element list, detaching and deleting the node (but not filtering it out).

If using 4.1, you can use subqueries instead for conditional cypher execution:

JB47394
Node Link

Thank you. The bits that I was missing were

  1. The use of EXISTS as a WITH expression (I've only done simple things with WITH)
  2. The use of the FOREACH pattern for conditional execution

3.5.20

And I guess I better update to 3.5.21