想象一下简单的Twitter场景:
所以例如在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
谢谢!
您遇到了"单一关系遍历"规则.在一个单一内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)
| 归档时间: |
|
| 查看次数: |
235 次 |
| 最近记录: |