Iterate through linked list and set attribute (counter) on each node

Hi , my cypher has become somewhat rusty ... i have a long list of nodes that have a rel (:PREV) to the previous node. So the 1st node in the list has an input rel, the middle nodes have 2 rels and the last node in the list has an outgoing rel.

Now i want to add the number 0 to the 1st node, 1 to the second etc and n-1 to the last node.

How would i do this in cypher ? So i have to find the 1st node (a node without outgoing rel) and follow (iterate through) the :PREV path upstream and update each node i come across and increase the counter ..

(node-1:X)<-[:PREV]-(node-2:X)<-[:PREV]-(node-3:X)<-............... <-[:PREV]-(node-n:X)

node 1 must get an attribute num=0
node 2 must get an attribute num=1
...
node n must get an attribute num=n-1

My list will be around 1.000.000 nodes long (every node on the list has other rels but not relevant for this i guess)

many thx for your ideas..

You could try this. This will find all the paths in your db and update each.

match path=(start:X)<-[:PREV*]-(end:X)
where not exists(()<-[:PREV]-(start))
and not exists((end)<-[:PREV]-())
with nodes(path) as nodes
unwind range(0,size(nodes)-1) as index
with nodes[index] as node, index
set node['num'] = index

Test Data:

create (:X{id:0})<-[:PREV]-(:X{id:1})<-[:PREV]-(:X{id:2})<-[:PREV]-(:X{id:3})<-[:PREV]-(:X{id:4})<-[:PREV]-(:X{id:5})<-[:PREV]-(:X{id:6})

Before update (num property is null for each node):

Executing update query:

After update (num property is set for each node):

Query if you want to update a specific path based on a given anchor node:

match path=(start:X)<-[:PREV*]-(end:X)
where start.id = 0
and not exists((end)<-[:PREV]-())
with nodes(path) as nodes
unwind range(0,size(nodes)-1) as index
with nodes[index] as node, index
set node['num'] = index

hi thanks !! will try this out reg koen

my graph as a list of 20.000 linked nodes and this hangs up teh system will test on smaller graph .. also maybe find a way to set the property when creating the nodes initially.. at the end i will have appr 1.000.000 nodes linked which sounds a lot for one long path..

update ... with a few nodes this works fine .. with list of 20000 nodes it fails .. guess we have to add the sequence number when creating the nodes (from file)

Are you remediating your data by running this to update all linked lists? If that is the cause it may be a memory issue. You could try batching the updates so the memory requirements are less.

Call {
  match path=(start:X)<-[:PREV*]-(end:X)
  where not exists(()<-[:PREV]-(start))
  and not exists((end)<-[:PREV]-())
  with nodes(path) as nodes
  unwind range(0,size(nodes)-1) as index
  with nodes[index] as node, index
  set node['num'] = index
} in transactions of 10000 rows 

Play around with the number of rows.

Hi, i get this error when using the call around the query..
A query with 'CALL { ... } IN TRANSACTIONS' can only be executed in an implicit transaction, but tried to execute in an explicit transaction.

any ideas how to bypass this ?

when i add auto: in froni of the call i get this

Ignored either because of an error or RESET

thx reg koen

@kdwykleingeld

are you running call {....} IN TRANSACTIONS via the Neo4j Browser?
if so preface the statement with :auto

Hi yes in the browser, i did prefix with :auto and that gave me the 'Ignored either because of an error or RESET' error..

This is the current query (which works fine on smaller datasets (without the auto/call addition) but not on my current dataset with 131000 linked nodes

:auto
call {
match path=(start:Block)<-[:PREVIOUS_BLOCK*]-(end:Block)
where not exists(()<-[:PREVIOUS_BLOCK]-(start))
and not exists((end)<-[:PREVIOUS_BLOCK]-())
with nodes(path) as nodes
unwind range(0,size(nodes)-1) as index
with nodes[index] as node, index
set node['height'] = index
} in transactions of 10000 rows

Try smaller batch sizes, 100 or 1000.

Hi yes i tried that with 1 10 100 1000 but i get exactly same error message:

So if i run below code:

:auto
call {
match path=(start:Block)<-[:PREVIOUS_BLOCK*]-(end:Block)
where not exists(()<-[:PREVIOUS_BLOCK]-(start))
and not exists((end)<-[:PREVIOUS_BLOCK]-())
with nodes(path) as nodes
unwind range(0,size(nodes)-1) as index
with nodes[index] as node, index
set node['height'] = index
} in transactions of 100 rows

I get this error :

ERROR N/A
Ignored either because of an error or RESET

any clues ?

One thing i noticed... at the end (when all data is loaded) it will be one long list of >880000 nodes. But currently i see that the graph contains several shorter lists that will be joined when more data is loaded (because the provious block pointer will be in one of those those input files) .... so currently it is not one big list (of 130 k nodes) but multiple shorter lists each with a start and end (so multiple 'paths') .. does that have impact on the algorothm ? guess not but that might break it .. will do some tesing with only one list - this works so guess the return of multiple paths is the issue here ... i will limit the search to starting with the 1st block

thx for all support !!

thx reg koen