Chris
Chris

Reputation: 815

Neo4J Cypher - Execute specific MATCH statement and return results depending on the result of an initial MATCH statement

I want to be able to return the result of a MATCH statement, and if no results are found for that statement, I want the query to then try a different MATCH statement. I am attempting to do this with a CASE statement, but I keep running into errors, specifically at the moment:

java.util.concurrent.CompletionException: org.neo4j.driver.v1.exceptions.ClientException: Invalid input ')': expected whitespace or a relationship pattern

MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})-[:INHERITS]-()-[:INCLUDES]-(p: itemProperty)
                                                  ^

Full Query:

MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})[:INCLUDES]-(p: itemProperty)
WITH ic, i, p, //only ever going to match on one (p: itemProperty) node
CASE WHEN COUNT(p) < 1 // when p node isn't found
THEN //try find a p node elsewhere
  MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})-[:INHERITS]-(i2: item)-[:INCLUDES]-(p: itemProperty)
END 
WITH p
OPTIONAL MATCH (p)-[r]-(pr:private)
WITH p, r, pr
RETURN p, COLLECT(DISTINCT r) AS rs, COLLECT(DISTINCT pr) AS prs

I'm not even sure if this is the appropriate and correct way to use the CASE statement. However, this is where I've come so far, and I am unsure as to even what the error is. Can I match a path inside the case statement? or is the problem the result of something else?

Any help with my current problem, or any other suggestions that may also work is very much appreciated.

EDIT: I have also noticed that if I have a comma after the WITH statment, e.g. WITH ic, i, p, then it will reach the error I have described above, but if I remove the last comma, it breaks with a different error on WHEN COUNT(p) < 1. Why is this the case? I haven't come across this behaviour before.

EDIT 2: I'm attempting to do the same thing a slightly different (simpler) way.

MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})[:INCLUDES]-(p: itemProperty)
WITH ic, i, p, COUNT(p) as p_count
MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})-[:INHERITS]-(i2: item)-[:INCLUDES]-(p2: itemProperty)
WITH p_count, p2
CASE WHEN p_count < 1 
THEN result = p2
ELSE result = p
END 
WITH result
OPTIONAL MATCH (result)-[r]-(pr:private)
WITH result, r, pr
RETURN result, COLLECT(DISTINCT r) AS rs, COLLECT(DISTINCT pr) AS prs

However, I get the following error:

java.util.concurrent.CompletionException: org.neo4j.driver.v1.exceptions.ClientException: Invalid input 'S': expected 'l/L' (line 6, column 4 (offset: 855))
"  WHEN p_count < 1"
 ^

I don't understand where the 'S' is coming from.

Upvotes: 0

Views: 291

Answers (1)

Luanne
Luanne

Reputation: 19373

In the first query, Invalid input ')': expected whitespace or a relationship pattern is because you're missing the - before [:INCLUDES] on the first line (i: item {id: "???"})[:INCLUDES]-(p: itemProperty) Also the usage of MATCH inside the CASE is not supported.

In the second example the same - is missing before [:INCLUDES] and the result in the CASE has to be aliased differently. This one should work

MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})-[:INCLUDES]-(p: itemProperty)
WITH ic, i, p, COUNT(p) as p_count
MATCH (ic: itemContainer {id: "???", version: 1})-[:CONTAINS]->(i: item {id: "???"})-[:INHERITS]-(i2: item)-[:INCLUDES]-(p2: itemProperty)
WITH p_count, p2,
CASE WHEN p_count < 1 
THEN  p2
ELSE p
END AS result
WITH result
OPTIONAL MATCH (result)-[r]-(pr:private)
WITH result, r, pr
RETURN result, COLLECT(DISTINCT r) AS rs, COLLECT(DISTINCT pr) AS prs

Upvotes: 1

Related Questions