Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
03-04-2021 11:57 AM
Hello,
I'm trying to get 3 visited posts after visit to blog index page and and then get related authors of these 3 posts.
There is relation PostVisit->Post->Author.
PostVisit is event.
When I have next 3 steps as path variable how do I access author info? I tried using [I in nodes(path)] but was only getting null values as result.
match path = (:PostVisit{url:"/blog/"})-[:NEXT*3]->(PostVisit{url:"/subscribe-to-updates/"})
Thanks for any suggestio
Solved! Go to Solution.
03-05-2021 09:31 AM
No, the query already does that.
Assume for the moment a graph like this
(:PostVisit{url:"/blog/"})-[:NEXT]->(:PostVisit {id:1})-[:NEXT]->(:PostVisit {id:2})-[:NEXT]->(:PostVisit {id:3})
When you run this query:
MATCH (:PostVisit{url:"/blog/"})-[:NEXT*..3]->(visit:PostVisit)
it will find 3 separate paths matching the pattern. On path one, visit
refers to the :PostVisit node with id: 1 (it traversed one :NEXT relationship and found a :PostVisit node. On path 2, it traversed two relationships and found the next :PostVisit node. On path 3 it traversed 3 relationships and found the last one.
So across the 3 records generated by the MATCH, visit
refers to each of those nodes, each one on its own row. A MATCH that continues from visit
to a connecting node will be executed on each row, and thus will find each :Author node per visit:
MATCH (:PostVisit{url:"/blog/"})-[:NEXT*..3]->(visit:PostVisit)
MATCH (visit)-->(:Post)-->(author:Author)
I did modify the query in my above post a bit. Originally you had this:
(:PostVisit{url:"/blog/"})-[:NEXT*3]->(PostVisit{url:"/subscribe-to-updates/"})
Which implies that from the /blog/ postVisit it will traverse 3 :NEXT relationships outgoing and find a :PostVisit with the url /subscribe-to-updates
. I wasn't sure if this was just an example case (where the third node has that url in your graph) or if you were specifically getting the path from the blog to the specified subscribe to updates node after traversing 3 :NEXT relationships.
But if this was what you wanted, you already know your start and end nodes and how many hops between them, then yes you can use [node in nodes(path) WHERE node:PostVisit]
to filter just to the :PostVisit nodes in the path. Then you can UNWIND them back to rows and MATCH the path to their post and author.
03-04-2021 08:58 PM
If you want to work with the next 3 post visits (instead of a post visit 3 steps away, which is what your current query is doing), then we can change the variable-length pattern to *..3
which means (from 1) up to 3. This has the added affect of being able to match to visits even if there are not 3 :NEXT relationships in the path in your graph. This way, the end node of the pattern can be used to match to the post and author.
MATCH (:PostVisit{url:"/blog/"})-[:NEXT*..3]->(visit:PostVisit)
MATCH (visit)-->(:Post)-->(author:Author)
...
I don't know what relationship types connect your :PostVisit, :Post, and :Author nodes, so you'll have to fill in the rest.
03-04-2021 11:23 PM
Hi Andrew, great, thanks for detailed explanation. And if I want to get authors of all posts in path, not just the final one, should I use apoc.path.spanningTree function?
03-05-2021 09:31 AM
No, the query already does that.
Assume for the moment a graph like this
(:PostVisit{url:"/blog/"})-[:NEXT]->(:PostVisit {id:1})-[:NEXT]->(:PostVisit {id:2})-[:NEXT]->(:PostVisit {id:3})
When you run this query:
MATCH (:PostVisit{url:"/blog/"})-[:NEXT*..3]->(visit:PostVisit)
it will find 3 separate paths matching the pattern. On path one, visit
refers to the :PostVisit node with id: 1 (it traversed one :NEXT relationship and found a :PostVisit node. On path 2, it traversed two relationships and found the next :PostVisit node. On path 3 it traversed 3 relationships and found the last one.
So across the 3 records generated by the MATCH, visit
refers to each of those nodes, each one on its own row. A MATCH that continues from visit
to a connecting node will be executed on each row, and thus will find each :Author node per visit:
MATCH (:PostVisit{url:"/blog/"})-[:NEXT*..3]->(visit:PostVisit)
MATCH (visit)-->(:Post)-->(author:Author)
I did modify the query in my above post a bit. Originally you had this:
(:PostVisit{url:"/blog/"})-[:NEXT*3]->(PostVisit{url:"/subscribe-to-updates/"})
Which implies that from the /blog/ postVisit it will traverse 3 :NEXT relationships outgoing and find a :PostVisit with the url /subscribe-to-updates
. I wasn't sure if this was just an example case (where the third node has that url in your graph) or if you were specifically getting the path from the blog to the specified subscribe to updates node after traversing 3 :NEXT relationships.
But if this was what you wanted, you already know your start and end nodes and how many hops between them, then yes you can use [node in nodes(path) WHERE node:PostVisit]
to filter just to the :PostVisit nodes in the path. Then you can UNWIND them back to rows and MATCH the path to their post and author.
03-05-2021 10:21 AM
Now I understand better how match works, thanks for explanation! What I need is what you described in *.. 3 example but I also have another query with fixed path length where I can use [x in nodes] logic. Thanks again!
All the sessions of the conference are now available online