Question

I am trying to understand if I can perform a query with Neo4j that contains both WITH and HAVING clauses. I have this so far:

MATCH (n)-[r:RELATIONSHIP*1..3]->(m) 
SET m:LABEL
WITH m
MATCH (m:LABEL)-[r2:RELATIONSHIP]->(q:OTHERLABEL)
WHERE r2.time<100
RETURN p,r2,q;

I'd now need to add in the same query something that in SQL would look

MATCH (n)-[r:RELATIONSHIP*1..3]->(m)
SET m:LABEL
WITH m
MATCH (m:LABEL)-[r2:RELATIONSHIP]->(q:OTHERLABEL)
WHERE r2.time<100 
    AND WHERE count(q)=3
RETURN m,r2,q;

I know that Cypher doesn't let me use that without using something like the HAVING clause but when I try to add it to my query it conflicts with the previous WITH clause. Is this feasible or it is too nested that Cypher won't allow me to do it?

Was it helpful?

Solution

You can have as many with statements as you want, it is just piping query results from one part to the next. Actually WITH + WHERE = `HAVING``

MATCH (n)-[r:RELATIONSHIP*1..3]->(m)
SET m:LABEL
WITH m
MATCH (m:LABEL)-[r2:RELATIONSHIP]->(q:OTHERLABEL)
WHERE r2.time<100 
WITH m,collect([r2,q]) as paths
WHERE length(paths) = 3
RETURN m,paths;

Btw. I don't know where your p comes from.

OTHER TIPS

Not sure what your reference is for HAVING in cypher, but that's not the problem with the query.

  • drop the second WHERE - in cypher, you WHERE once and then you can expand that with all the binary fun you want
  • your first filter condition tests individual relationships (r2), but the second tests an aggregate (count(q)). You can't test a flat pattern and an aggregate from the same pattern at the same time
  • return things that you have actually bound (what is p?)

You may also want to change the second MATCH, m is already bound but you are re-matching it with the just created label. All in all, try something like

MATCH (n)-[r:RELATIONSHIP*1..3]->(m)
SET m:LABEL
WITH m
MATCH (m)-[r2:RELATIONSHIP]->(q:OTHERLABEL)
WHERE r2.time<100
WITH m, collect(r2) as rr, collect(q) as qq
WHERE length(qq) = 3
RETURN p,rr,qq;

for filtering first on flat relationship r2 then on size of aggregate, or for a flat WHERE .. AND .. try something like

MATCH (n)-[r:RELATIONSHIP*1..3]->(m)
SET m:LABEL
WITH m
MATCH (m)-[r2:RELATIONSHIP]->(q:OTHERLABEL)
WHERE r2.time<100 AND q.someProp = 10
RETURN m,r2,q;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top