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.
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?
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:
Thank you. The bits that I was missing were
- The use of EXISTS as a WITH expression (I've only done simple things with WITH)
- The use of the FOREACH pattern for conditional execution
And I guess I better update to 3.5.21