Guaranteed order

I have the following query:

MATCH path=(p)<-[r:partOf*0..]-(a:Node)
    WHERE elementId(a) = '<some parameter>' 
    WITH a, COLLECT (p.body) AS ancestors
    RETURN
    a.someattributes AS attributes,
    a.body AS body,
    ancestors

the body attribute of each of the nodes is a JSON file, making my query I get:

[ "{ json body reference }", "{ json parent reference }", "{ json grand parent reference }", "{ json great grand parent reference }", "{ json root reference }"]

is it guaranteed that the list is always returned ordered?

@joshcornejo

if you want guarenteed order your need to use a ORDER BY clause.
Without it, It may be ordered today but given no ORDER BY clause, if you upgrade it may or may not still maintain order

Sorry, i don't get it?

(a {body:'{son}'})-[:partOf]->(b {body:'{dad}'})-[:partOf]->(c {body:'{granddad}'})-[:partOf]-(d {body:'{greatgp}'})

the list of the body property comes inside the COLLECT (p.body) and there is no attribute to order, other than the fact that there is the [:partOf] relationship which defines the hierarchy, which isn't necessarily chronologically meaningful (this is a linear example, but the ancestry could be a graph and I could associate some today, some other tomorrow in any sequence).

the ancestors that contains 'body' list has [ {son}, {dad}, {granddad}, {greatgp} ] which are in the right order, but I don't know if the path/collect combination provides the guaranteed order.

If you are referring to the order of your ancestors list, it has been my experience that a variable length will return the list in the same order. It is not guaranteed as @dana_canzano stated. You could approach it differently so you get back a list in the same order. Instead of getting a list of paths back with increasing length until the end is reached, then collecting the end node of each path, you could get one path path that represents the longest path and get the nodes along the path. It is my experience the collection of nodes in this case will be ordered by their position along the path.

MATCH path=(p)<-[r:partOf*0..]-(a:Node)
    WHERE elementId(a) = '<some parameter>' 
    AND not exists(()<-[r:partOf]-(p))
    WITH a, [i in nodes(path) | i.body] AS ancestors
    RETURN
    a.someattributes AS attributes,
    a.body AS body,
    ancestors

If your body attribute contains json objects as a string, you can convert them to neo4j maps

for the 4 node hiearchy, this new way returns 4 rows

<a's attributes> [ {son} ]
<a's attributes> [ {son}, {father} ]

... i only need (and from my query already get):

<a's attributes> [ {son}, {dad}, {grandad}, {greatgp}]

and to know that the list of bodies is always ordered from leaf to root

You should only get one row if only one path originates from ‘a’. The cause must be my oversight, as I cut and pasted and didn’t pay attention to the variable ‘r’ bound to the relationship.

Try this.

MATCH path=(p)<-[r:partOf*0..]-(a:Node)
    WHERE elementId(a) = '<some parameter>' 
    AND not exists(()<-[:partOf]-(p))
    WITH a, [i in nodes(path) | i.body] AS ancestors
    RETURN
    a.someattributes AS attributes,
    a.body AS body,
    ancestors

My experience is that the results returned from a variable length search will be in the order of length. That being said you should not rely on that as it is implementation dependent and neo4j can change that at anytime.

If you want to ensure the order, you can order by path length before collecting.

MATCH path=(p)<-[r:partOf*0..]-(a:Node)
    WHERE elementId(a) = '<some parameter>' 
    WITH a, p, path
    ORDER BY length(path)
    WITH a, COLLECT (p.body) AS ancestors
    RETURN
    a.someattributes AS attributes,
    a.body AS body,
    ancestors
1 Like