简体   繁体   中英

Neo4j Cypher: why does this 0-length path not MATCH?

Imagine a simple Twitter scenario:

  • Alice tweets something (id 1).
  • Bob replies with something (id 2).

So eg in Cypher:

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

I want to write a query that, for any tweet, returns the tweet and the author alongside the very first/original tweet and author in that conversation.

So for tweet 1, it should return 1, Alice, 1, Alice , but for tweet 2, it should return 2, Bob, 1, Alice .

Here's my query:

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

(I know I could achieve this with an OPTIONAL MATCH , but achieving this with a potential zero-length path instead would be helpful to me for other reasons.)

This works great on tweet 2, but doesn't return any results for tweet 1. I'm at a loss for why, but I'm sure I'm missing something obvious. Any ideas?

(When I say the query out loud, it seems fine. Tweet 2 has an author; it with a zero-length reply chain, it is the original; it as the original still has an author; and it as the original is not in reply to any other tweet.)

Here's a live console to play with:

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

Thanks!

You're encountering the "single relationship traversal" rule. Within a single MATCH , you can only traverse any relationship once. This is very helpful in the 90% case, to prevent matches that loop or track back over relationships.

However, in your case this means that the second part of your match cannot use the same relationship used in the first part. Hence it's not matching.

The solution is simple - use a separate MATCH clause:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM