Karel Horak
Karel Horak

Reputation: 1072

Neo4j: Transitive query and node ordering

I am using Neo4j to track relationships in OOP architecture. Let us assume that nodes represent classes and (u) -[:EXTENDS]-> (v) if class u extends class v (i.e. for each node there is at most one outgoing edge of type EXTENDS). I am trying to find out a chain of predecessor classes for a given class (n). I have used the following Cypher query:

start n=node(...)
match (n) -[:EXTENDS*]-> (m)
return m.className

I need to process nodes in such an order that the direct predecessor of class n comes first, its predecessor comes as second etc. It seems that the Neo4j engine returns the nodes in exactly this order (given the above query) - is this something I should rely on or could this behavior suddenly change in some of the future releases?

If I should not rely on this behavior, what Cypher query would allow me to get all predecessor nodes in given ordering? I was thinking about following query:

start n=node(...)
match p = (n) -[:EXTENDS*]-> (m {className: 'Object'})
return p

Which would work quite fine, but I would like to avoid specifying the root class (Object in this case).

Upvotes: 2

Views: 1734

Answers (1)

BtySgtMajor
BtySgtMajor

Reputation: 1462

It's unlikely to change anytime soon as this is really the nature of graph databases at work.

The query you've written will return ALL possible "paths" of nodes that match that pattern. But given that you've specified that there is at most one :EXTENDS edge from each such node, the order is implied with the direction you've included in the query.

In other words, what's returned won't start "skipping" nodes in a chain.

What it will do, though, is give you all "sub-paths" of a path. That is, assuming you specified you wanted the predecessors for node "a", for the following path...

(a)-[:EXTENDS]->(b)-[:EXTENDS]->(c)

...your query (omitting the property name) will return "a, b, c" and "a, b". If you only want ALL of its predecessors, and you can use Cypher 2.x, consider using the "path" way, something like:

MATCH p = (a)-[:EXTENDS*]->(b)
WITH p
ORDER BY length(p) DESC
LIMIT 1
RETURN extract(x in nodes(p) | p.className)

Also, as a best practice, given that you're looking at paths of indefinite length, you should likely limit the number of hops your query makes to something reasonable, e.g.

MATCH (n) -[:EXTENDS*0..10]-> (m)

Or some such.

HTH

Upvotes: 4

Related Questions