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

Ase*_*ore 2 neo4j cypher

想象一下简单的Twitter场景:

  • 爱丽丝推特(id 1).
  • Bob回复了一些东西(id 2).

所以例如在Cypher:

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

我想编写一个查询,对于任何推文,都会返回推文和作者以及该对话中的第一个/原始推文和作者.

所以对于推文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
Run Code Online (Sandbox Code Playgroud)

(我知道我可以通过一个OPTIONAL MATCH实现这个目标,但是通过潜在的零长度路径来实现这一目标反而对我有帮助.)

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

(当我大声说出查询时,似乎很好.推文2有一个作者;它有一个零长度的回复链,它是原始的;它原来还有一个作者;它原来不是回复任何其他推文.)

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

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

谢谢!

Chr*_*man 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
Run Code Online (Sandbox Code Playgroud)