Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get nth element of a collection in Cypher

Using Cypher 1.8, there are some functions working on collections and returning a single element:

HEAD( expression ):

START a=node(2)
RETURN a.array, head(a.array)

LAST( expression ):

START a=node(2)
RETURN a.array, last(a.array)

However, I could not find a function to return the nth element of a collection. What am I missing?

like image 890
Fynn Avatar asked Dec 16 '12 18:12

Fynn


3 Answers

There's no good way to do that at the moment. Please submit a feature request at https://github.com/neo4j/neo4j

I've seen people do head(tail(tail(tail(coll)))), and while it's probably acceptably fast, it still makes me a little ill to see in a query, especially if you're talking about the 17th element or worse.

Example: http://console.neo4j.org/r/bbo6o4

Update: Here's a way to do it using reduce and range. It makes it so you can give a parameter for nth at least, even though it still makes me cringe:

start n=node(*) 
with collect(n) as allnodes 
return head(reduce(acc=allnodes, x in range(1,3): tail(acc)));

http://console.neo4j.org/r/8erfup

Update 2 (8/31/2013):
The new collection syntax is now merged into 2.0 and will be theoretically be a part of M05! So, you'll be able to do:

start n=node(*)
with collect(n) as allnodes
return allnodes[3]; // or slices, like [1..3]

I'll add a link to the snapshot documentation when it gets updated.

like image 186
Eve Freeman Avatar answered Sep 27 '22 22:09

Eve Freeman


Currently, with the release of APOC Procedures 3.3.0.2 you can use aggregation functions.

This way, you can do thinks like:

create (:Node {node_id : 1}),
    (:Node {node_id : 2}),
    (:Node {node_id : 3});

match(n:Node)
with n order by n.node_id
// returns {"node_id":2}  
return apoc.agg.nth(n, 1);

or:

match(n:Node)
with n order by n.node_id
// returns {"node_id":1} 
// you can also use apoc.agg.last
return apoc.agg.first(n);

To work with lists UNWIND the list first:

with ['fist', 'second', 'third'] as list
unwind list as value
// returns 'second'
return apoc.agg.nth(value, 1);
like image 42
Bruno Peres Avatar answered Sep 27 '22 22:09

Bruno Peres


I've just come across this old question, and for the benefit of anyone else recently coming across it... it seems the list support has improved.

From the Cypher 4 list docs:

Cypher has comprehensive support for lists.

^ Sidenote: I think that's list comprehensions pun? ;-)

They go on to give an example showing how you'd access the n'th element of a list:

To access individual elements in the list, we use the square brackets again. This will extract from the start index and up to but not including the end index. ... we’ll use the range function. It gives you a list containing all numbers between given start and end numbers. Range is inclusive in both ends.

RETURN range(0, 10)[3]
^ returns "3"
like image 30
Peter W Avatar answered Sep 27 '22 21:09

Peter W