时间:2018-04-21 23:25:17

标签: neo4j cypher

我对这个问题感到困惑,我认为答案很简单,所以让我切入它。

给出如下图:

Diagram of graph

由看起来像这样的查询创建:

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

降至0行
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如何搜索这些模式。有谁有洞察可能是什么?谢谢你的时间!

1 个答案:

答案 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条款之间没有任何独特性。