Domanda

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?

È stato utile?

Soluzione

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.

Altri suggerimenti

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;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top