Neo4j Cypher:为什么这个0长度的路径不匹配?

时间:2014-07-08 15:32:16

标签: neo4j cypher

想象一下简单的Twitter场景:

  • Alice发推文(id 1)。
  • 鲍勃回答了一些事情(身份证2)。

所以,例如在Cypher:

CREATE
    (parent:Tweet {id: 1}) -[:AUTHOR]-> (:User {name: 'Alice'}),
    (child:Tweet {id: 2}) -[:AUTHOR]-> (:User {name: 'Bob'}),
    (child) -[:IN_REPLY_TO]-> (parent)

我想写一个查询,对于任何推文,都会将推文和作者与该对话中的第一个/原始推文和作者一起返回。

因此,对于推文1,它应该返回1, Alice, 1, Alice,但对于推文2,它应该返回2, Bob, 1, Alice

这是我的疑问:

MATCH
    (tweet:Tweet {id: {id}}) -[:AUTHOR]-> (author:User),
    (tweet) -[:IN_REPLY_TO*0..]-> (original:Tweet) -[:AUTHOR]-> (originalAuthor:User)

WHERE NOT(original -[:IN_REPLY_TO]-> ())

RETURN tweet, author, original, originalAuthor

(我知道我可以使用OPTIONAL MATCH来实现这一点,但是使用潜在的零长度路径来实现这一点对我来说会有其他原因。)

这在推文2上效果很好,但是不会为推文1返回任何结果。我为什么不知所措,但我确信我错过了一些明显的东西。有什么想法吗?

(当我大声说出问题时,看起来很好。推文2有一个作者;它有一个零长度的回复链,它是原始的;它原来还有一个作者;它作为原始不回复任何其他推文。)

这是一个可以玩的实时控制台:

http://console.neo4j.org/r/d719lz

谢谢!

1 个答案:

答案 0 :(得分:5)

您正在遇到单一关系遍历"规则。在单个MATCH内,您只能遍历任何关系一次。这在90%的情况下非常有用,可以防止循环或跟踪关系的匹配。

但是,在您的情况下,这意味着您的匹配的第二部分不能使用第一部分中使用的相同关系。因此,它不匹配。

解决方案很简单 - 使用单独的MATCH子句:

MATCH (tweet:Tweet {id: {id}}) -[:AUTHOR]-> (author:User),
MATCH (tweet) -[:IN_REPLY_TO*0..]-> (original:Tweet) -[:AUTHOR]-> (originalAuthor:User)
WHERE NOT(original -[:IN_REPLY_TO]-> ())
RETURN tweet, author, original, originalAuthor