Access nodes in path

Hi,
I’m working on a small buses lines dataset, I’m currently hitting a problem.
How can I check that, on a line with X buses, the previous bus isn’t after the next one using this kind of MATCH:

MATCH p=(a)-[*1..4]->(b)
 WHERE a.arrival_date + duration({ minutes: 5}) <= b.departure_date
 AND b.departure_date <= a.arrival_date + duration({ hours: 1})
RETURN nodes(p);

Because on this example a & b filtering are more like this if I’m right:
(a)-->()-->()-->(b)
So I can’t control this part:
()-->()
I’m sure it’s not that complicated but I can’t find the way, I think UNWIND can be what I’m looking for, but how?

You can use nodes(path) to get the list of nodes that makes up the path, where the first node in the list is a and the last node in the list is b.

It may be a bit complicated, but if you want to work with adjacent pairs in the path, you can leverage APOC Procedures to get this, but you'll need to do a bit of aliasing and use UNWIND as well. Something like this:

MATCH p=(a)-[*1..4]->(b)
 WHERE a.arrival_date + duration({ minutes: 5}) <= b.departure_date
 AND b.departure_date <= a.arrival_date + duration({ hours: 1})
UNWIND apoc.coll.pairsMin(nodes(p)) as pair
WITH p, pair[0] as first, pair[1] as next
WHERE // add any predicates you want here for each adjacent pair of nodes in the path
RETURN nodes(p);

Pretty interesting, thank you @andrew_bowman !
I had an issue as I need to check three nodes in row instead of two so I tried to use apoc.coll.partition instead of apoc.coll.pairsMin.
But apoc.coll.partition crashed saying :

Neo.ClientError.Statement.SyntaxError: Unknown function apoc.coll.partition

Which is strange as apoc.coll.pairsMin is correctly loaded.
Any idea @andrew_bowman ?

It's not registred.


I'm using apoc version "3.5.0.1" but it seems to be released 2 years ago now.

Even after an update to Neo4J 3.5.4 and APOC to 3.5.0.3 it seems that it's still not accessible.
But what is strange is that it seems it exist.

call apoc.help('coll');
"procedure" "apoc.coll.partition" "apoc.coll.partition(list,batchSize)" "apoc.coll.partition(values :: LIST? OF ANY?, batchSize :: INTEGER?) :: (value :: LIST? OF ANY?)" null null

My neo4j.conf says : dbms.security.procedures.unrestricted=apoc.*

This is because apoc.coll.partition() is a procedure, not a function. As such, you can't use it as an expression, but must use the CALL apoc.coll.partition() YIELD value syntax.

Hi,
Thanks @andrew_bowman if I remember correctly that's not clearly written on the doc.
Thanks anyway, now it works :slight_smile:
Have a pleasant day.

While it is noted that it's a procedure from apoc.help(), it could use a callout in the docs, as nearly all the other apoc.coll.* items here are functions. I'll see about addding that in.

Hi @andrew_bowman,
It seems that if we have more than two nodes it does not works correctly.
For example, with two nodes, both will be treated by pairsMin but when I have another one (so 3 nodes) node 2 and 3 aren't unpacked together by pairsMin.
Do you have another solution ?
I'm a bit out of solutions right now :confused:

BTW I just saw that it skip alone nodes.
If (a) is enough then pairsMin will skip it.

It seems that if we have more than two nodes it does not works correctly.
For example, with two nodes, both will be treated by pairsMin but when I have another one (so 3 nodes) node 2 and 3 aren't unpacked together by pairsMin.

I'm not sure what you mean by this.

As an example, with 3 elements:

return apoc.coll.pairsMin([1,2,3])

You'll correctly get two elements in the list, the pair of [1,2] and the pair of [2,3].

Hi @andrew_bowman,

It seems that you are right, my bad.
The pairs are [1,2] then [2, 3].
But I still have the problem when I don't have a pair. Like [1, NULL] I will try to coalesce it.