为何Cypher查询会创建多条无关关系?求官方文档依据
Great question—this behavior is rooted in how Cypher processes queries row-by-row, a core part of its execution model. Let me break down the official reasoning, your specific cases, and how this works across different match patterns.
Official Core Logic (From Neo4j's Cypher Specification)
Cypher operates on a row-based execution model: every time your MATCH clauses produce a set of matching rows (each containing the variables defined in the match), any subsequent write operations (like CREATE, MERGE, SET) will run once per row.
Even if you don’t use all the variables from the MATCH clauses in your CREATE, each row still triggers the write operation independently. This is explicitly documented in Neo4j’s Cypher documentation as part of the query execution flow—matches generate rows, and each row drives the subsequent steps.
Breaking Down Your Examples
First Query: 5 LIVE_IN Relationships & Places
Your first query:
MATCH(p:Person {id:1}) MATCH (p)-[:KNOWS]-(s) CREATE (p)-[:LIVE_IN]->(:Place {name: 'Some Place'})
- The first
MATCHfinds 1Personnode (p). - The second
MATCHfinds 5 nodes (s) connected topviaKNOWS(since-(s)is undirected, it counts both incoming and outgoingKNOWSrelationships). - Together, these two matches produce 5 rows (each row has
pand one uniques). - The
CREATEruns once per row, so you get 5Placenodes and 5LIVE_INrelationships frompto each place.
Second Query: 15 LOVE Relationships & Places
Your second query adds a third MATCH for Office nodes:
MATCH(p:Person {id:1}) MATCH (p)-[:KNOWS]-(s) MATCH (o:Office) CREATE (p)-[:LOVE]->(:Place {name: 'Any Place'})
- Now you have three match clauses: 1
p, 5s, 3o. - The Cartesian product of these is
1 * 5 * 3 = 15 rows(every combination ofp,s, ando). - Again,
CREATEruns once per row, leading to 15Placenodes and 15LOVErelationships.
CREATE Behavior in Complex Match Patterns
This row-by-row logic applies regardless of the match pattern’s structure:
- Non-connected graphs: If you match two unrelated node sets (e.g.,
MATCH (a:LabelA), (b:LabelB)), you get a Cartesian product of allaandbnodes, andCREATEruns once for each combination. - Tree structures: If your
MATCHtraverses a tree (e.g.,MATCH (root)-[:CHILD*]->(leaf)), every path from root to leaf becomes a row, andCREATEruns once per path. - Optional matches:
OPTIONAL MATCHadds rows withNULLvalues for unmatched variables, so those rows still triggerCREATEunless you filter them out.
If you want to avoid this (e.g., run CREATE only once, regardless of matches), use WITH to limit the number of rows before the write operation. For example:
MATCH(p:Person {id:1}) MATCH (p)-[:KNOWS]-(s) WITH p LIMIT 1 // Keep only one row with p CREATE (p)-[:LIVE_IN]->(:Place {name: 'Some Place'})
This will create just one Place and one LIVE_IN relationship, even if there are 5 s nodes.
Impact of KNOWS Relationship Direction
The direction in your MATCH clause directly affects how many rows are generated:
(p)-[:KNOWS]-(s): Undirected match, counts bothp → sandp ← srelationships. Ifphas 3 outgoing and 2 incomingKNOWSrelationships, this returns 5 rows.(p)-[:KNOWS]->(s): Directed match, only counts outgoing relationships fromptos. Ifphas 3 outgoing, this returns 3 rows.(p)<-[:KNOWS]-(s): Directed match, only counts incoming relationships topfroms. Ifphas 2 incoming, this returns 2 rows.
More rows mean more CREATE executions, so direction directly impacts the number of nodes/relationships created.
内容的提问来源于stack exchange,提问作者adnanmuttaleb

