2

How do you conditionally do a SET (or anything else) based on the result of a previous line? So for example the query below (which doesn't work atm), where I'm trying to update something based on if the count is 1 (and not do it otherwise). Query doesn't like statements after THEN so that's where the error is occurring. I've tried also using WHERE clauses but no luck as of yet.

Is there any other way to accomplish what I'm trying to do below in a single query?

MATCH (n:Thing { name: 'asdf' })
OPTIONAL MATCH (p:Thing)-[:HAS_CHILD]->(n)
OPTIONAL MATCH (c)<-[:HAS_CHILD]-(p:Thing)
WITH c, p, n,
CASE count(c)
WHEN 1
THEN SET p.btogstate = 'closed'
DETACH DELETE n

Update

Tried the following based on a similar post but still no luck:

MATCH (n:Thing { name: 'asdf' })
OPTIONAL MATCH (p:Thing)-[:HAS_CHILD]->(n)
OPTIONAL MATCH (c)<-[:HAS_CHILD]-(p:Thing)
WITH c, p, n,
CASE WHEN count(c) = 1 then [1] else [] end as countOne
FOREACH (x in countOne | SET p.btogstate = 'closed'
DETACH DELETE n

Update 2 (final)

While cybersam's solution worked in a particular situation, the following was the only thing that ended up working for my particular situation for reasons that I still don't understand, so here it is for anyone that might run into similar weirdness. The main difference is that instead of using count to see if there was more than one child for the parent node, I just did another match to see if there was anything else that was a child of the parent node that wasn't the originally matched child (i.e. where n<>y). If there was not (i.e. y is null) then update the property, if there was (i.e. y is not null) then don't do anything other than delete n:

MATCH (n:Thing { name: 'asdf' })
OPTIONAL MATCH (p:Thing)-[:HAS_CHILD]->(n)
with p, n
OPTIONAL MATCH (p)-[:HAS_CHILD]->(y)
WHERE n<>y
WITH n, y, p,
CASE WHEN y IS NULL then [1] else [] end as countOne
FOREACH (x in countOne | SET p.btogstate = 'closed')
DETACH DELETE n;
Jason Simpson
  • 4,653
  • 5
  • 16
  • 26
  • Do you really want to `DETACH DELETE n` (that is, delete `n` and all its relationships) -- no matter what? – cybersam Jun 07 '17 at 01:33
  • @cybersam yep, n needs to completely go away, but the node that had a [:HAS_CHILD] relationship with it needs a property updated (btogstate) since it's been deleted, since that property is only a certain value if it has a child (n) – Jason Simpson Jun 07 '17 at 01:35
  • Also, do you really require that there be exactly 1 `c` in order to set that property? – cybersam Jun 07 '17 at 01:37
  • @cybersam yep, if it's anything higher than 1 then I don't want to set the property – Jason Simpson Jun 07 '17 at 01:38

2 Answers2

1

Try this:

MATCH (n:Thing { name: 'asdf' })
OPTIONAL MATCH (p:Thing)-[:HAS_CHILD]->(n)
OPTIONAL MATCH (c)<-[:HAS_CHILD]-(p:Thing)
WITH c, p, n
FOREACH(x IN (CASE WHEN c IS NULL THEN [] else [1] END) |
  DETACH DELETE n
)

Based on this Mark Needham post (Neo4j: LOAD CSV – Handling conditionals).

Bruno Peres
  • 15,845
  • 5
  • 53
  • 89
1

This should work:

MATCH (n:Thing { name: 'asdf' })
OPTIONAL MATCH (c)<-[:HAS_CHILD]-(p:Thing)-[:HAS_CHILD]->(n)
WITH p, n,
  CASE WHEN COUNT(c) = 1 then [1] else [] end as countOne
FOREACH (x in countOne | SET p.btogstate = 'closed')
DETACH DELETE n;

Notice that, unlike your original query, the WITH clause does not include c by itself, as that would prevent the aggregation function COUNT from working as expected (in that case, the count would always have a value of 1 if the optional match found any matches).

cybersam
  • 63,203
  • 6
  • 53
  • 76
  • This works, thank you very much! For some reason it's not working in my code though. Will have to investigate why. – Jason Simpson Jun 07 '17 at 01:53
  • I added another sentence to my answer. That might help. – cybersam Jun 07 '17 at 01:58
  • I thought this worked but then upon further inspection the property (p.btogstate) is not getting set even though a query that just does the count does indeed return 1 – Jason Simpson Jun 07 '17 at 02:54
  • Works for me. I first ran this query: `CREATE (n:Thing { name: 'asdf' }), (c)<-[:HAS_CHILD]-(p:Thing)-[:HAS_CHILD]->(n) `, and then ran my answer. The `n` node was deleted and the `p` node had the expected new property. Is your data model different than what was presented in the question? – cybersam Jun 07 '17 at 03:01
  • I just tried your create and your solution and it worked, so I'll mark as solved. But there really is no difference between the two (that my tired eyes can spot anyway). Plus some of my queries for count decide to work sometimes and not others. I have no idea...I don't know if there is something wrong with my DB or what. Thank you as usual though for your help :) – Jason Simpson Jun 07 '17 at 03:16