Getting cross-join behaviour on linked match

Hi there

I have a graph based on educational data that I am trying to filter. This code seems to create a cross-join effect in terms of the resultant rows, even though l is constrained to s

MATCH (s:School)-[r:PART_OF]->(l:LEA),
(l)-[:HAS_EXAM]->(e:Exam),
(l)-[:HAS_TERM]->(t:Term),
(l)-[:HAS_HOLIDAY]->(h:Holiday)

This should bring back just a dozen or so rows but it returns thousands like a cross-join with unrelated match clauses.

I then thought, "ah, I need to refer to the same relationship" and I then tried this:

MATCH (s:School)-[r:PART_OF]->(l:LEA),
(s)-[r:PART_OF]->(l)-[:HAS_EXAM]->(e:Exam),
(s)-[r:PART_OF]->(l)-[:HAS_TERM]->(t:Term),
(s)-[r:PART_OF]->(l)-[:HAS_HOLIDAY]->(h:Holiday)

but this doesn't work either as you can't appear to refer to r more than once.

What am I doing wrong?

Thanks in advance

You're right that this is returning a cross join.

Per row, with your current queries, only one node can fill in per variable in the pattern.

Per row, you will get: 1 node for s, 1 node for l, one node for e, one node for t, one node for h.

Since there are multiple paths which match the pattern, each row corresponds with a separate path, the variables then referring to the specific nodes on the matched path.

I think what you're going for instead is to get collections of various results, so that per single school (maybe), you want a collection of exams, a collection of terms, a collection of holidays, all of that for a single school per row.

You need to make use of collect() in between your matches or use pattern comprehensions from your s node so your results will be grouped automatically.

I don't know what a :LEA node is supposed to be, so I'm not sure how that fits into your desired groupings.