cancel
Showing results for 
Search instead for 
Did you mean: 

Access related nodes on variable path

TimoSpa
Node

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

1 ACCEPTED SOLUTION

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.

View solution in original post

4 REPLIES 4

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.

TimoSpa
Node

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?

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.

TimoSpa
Node

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!