我对这个问题感到困惑,我认为答案很简单,所以让我切入它。
给出如下图:
由看起来像这样的查询创建:
CREATE (simpsons:Family {name: "Simpson"})
CREATE (homer:Father {name: "Homer"})
CREATE (lisa:Daughter {name: "Lisa"})
CREATE (snowball:Pet {name: "snowball"})
CREATE (lisa)-[:owns]->(snowball)-[:has]->(:Item {name: "catnip"})
CREATE (homer)-[:has]->(:Item {name: "beer"})
CREATE (lisa)-[:has]->(:Item {name: "saxophone"})
CREATE (lisa)<-[:memberOf]-(simpsons)-[:memberOf]->(homer)
为什么看起来像这样的查询会失败?
MATCH (f:Family),
(f)-[*1..10]-(lisa:Daughter),
(lisa)-[*1..10]-(:Item {name: "saxophone"}),
(f)-[*1..10]-(snowball:Pet),
(snowball)-[*1..10]-(:Item {name: "catnip"})
RETURN f;
单独使用,它的两个组件都找到匹配。
MATCH (f:Family),
(f)-[*1..10]-(lisa:Daughter),
(lisa)-[*1..10]-(:Item {name: "saxophone"})
RETURN f;
和
MATCH (f:Family),
(f)-[*1..10]-(snowball:Pet),
(snowball)-[*1..10]-(:Item {name: "catnip"})
RETURN f;
但是当拼凑在一起时没有匹配。
我已经尝试PROFILE
查询,看起来Cypher从Snowball向后工作。它可以在家庭和Snowball之间建立第一个连接。
之后它会执行VarLengthExpand(All)
snowball, f, lisa
(f)-[ UNNAMED22:*..10]-(lisa)
产生6行。然后我们使用此Filter
:
snowball, f, lisa
lisa: Daughter
如果我在match语句的第一行声明了一个系列和一个女儿之间的连接,我可以让匹配工作,但由于我必须做特定应用的原因,这不是一个有用的解决方法。
MATCH (f:Family)-[*1..10]-(lisa:Daughter),
(lisa)-[*1..10]-(:Item {name: "saxophone"}),
(lisa)-[*1..10]-(snowball:Pet {name: "snowball"})-[*1..10]-(:Item {name: "catnip"})
RETURN f;
我想我忽略了Cypher如何搜索这些模式。有谁有洞察可能是什么?谢谢你的时间!
答案 0 :(得分:1)
这不是Cypher的错误,这是给定MATCH模式中关系唯一性的副作用。
来自uniqueness section of the docs:
在模式匹配时,Neo4j确保不包含在单个模式中多次发现相同图形关系的匹配。
这种类型的唯一性通常是正确的,并且在使用遍历循环的可变长度关系时非常适合防止无限循环。
MATCH或OPTIONAL MATCH中的模式保留了关系唯一性,即使这些模式包含多个逗号分隔的路径,如您的情况。
您拥有单个MATCH模式中的所有路径,因此关系必须是唯一的;如果在一条路径中使用,它们将不会被重用于另一条路径。
真正的问题在于:(f)-[*1..10]-(snowball:Pet)
因为你早先<memberOf
已经遍历了同样的关系(辛普森和丽莎之间的(f)-[*1..10]-(lisa:Daughter)
)。由于关系不能被重用,这两个路径中的一个将无法匹配,因此整个MATCH失败......没有这种模式存在唯一关系。
请注意,当您将单个MATCH分解为多个MATCH时,如stdob--
的答案,查询成功。在单独的MATCH条款之间没有任何独特性。