Cypher Query for updating a list of nodes

I am having a json array of user detail nodes and I do loop over it and check if a node already exists with the specific numeric id property; if it exists then check the 'id' property of the node, if the 'id' is numeric( isdigit ) then do nothing but if 'id' is not numeric property then update the ' id ' property and set it to the ' numeric_id '.

for x in all_json:
    f_id = x.get("id",'')
    f_num_id = x.get('numaric_id','')
    tnode = self.find_user_friend(f_num_id, uid) 
    if tnode is not None:
         #### Update id to numeric id #####
         if tnode['n']['id'].isdigit():
            pass
         else:
             tnode['n']['id'] = f_num_id
             tnode['n'].push()

find_user_friend function is

def find_user_friend(self, t_id, u_id):
        """
            To search for target with respective user
        """
        tnode=None
        query = """
        Match (n:Friend {type:"1"}) where n.numaric_id={tid} and n.uid = {uid} return n
        """
        result = self.graph.run(query, parameters={'tid':str(t_id), 'uid':int(u_id)})
        if result.forward() > 0:
            tnode = result.current()

The current process takes time as it searches for every individual node then checks and then update the node. I am looking for the optimized solution. I am beginner in neo4j and familiar with UNWIND and FOREACH in neo4j but can't really made it for now.

Here is what I tried.

list_arr = [{id:"amey",numaric_id:"123"},{id:"12",numaric_id:"12"},{id:"amiey",numaric_id:"113"}]

            UNWIND """+ l +""" as c
            Match (n:Friend {numaric_id : c.numaric_id , uid : '1', type:"1"})
            SET n.id = numaric_id

Help will be appreciated

UNWIND is the way to go, but the way you're passing your array to the query isn't going to work. This:

UNWIND """+ l +""" as c

Is trying to unwind a string!

The thing to do is to submit your python array as a parameter, and then unwind the parameter. Something like this:

query = """
UNWIND $inputArray AS c
Match (n:Friend {numaric_id : c.numaric_id , uid : '1', type:"1"})
            SET n.id = numaric_id
"""
self.graph.run(query, parameters={'inputArray': l})

Hi david,
Thanks for responding. What if we unwind a string then how can it be handled?

Like this:

l = '[{id:"amey",numaric_id:"123"},{id:"12",numaric_id:"12"},{id:"amiey",numaric_id:"113"}]'

You simply can't unwind a string; unwind only works on lists/arrays. I dunno -- I guess it might work, if it did, a string would unwind to individual characters?

Given your array you want to unwind it to individual objects with id/numaric_id keys and process each of these sequentially.

Doing something like this """ + l + """ interpolates the python string representation of the array into an actual string, which is not the same thing.

Looks like this is a JSON string. You would need to first convert this into a structure (a list of maps), then you could UNWIND the list so you have a map on each row.

You can use APOC convert functions for this:

WITH '[{id:"amey",numaric_id:"123"},{id:"12",numaric_id:"12"},{id:"amiey",numaric_id:"113"}]' as inputString
WITH apoc.convert.fromJsonList(inputString) as list
UNWIND list as row
RETURN row.numaric_id

If the JSON string is the input, then just use apoc.convert.fromJsonList() on the parameter.

it's not JSON as the keys are lacking quotations around them. It's a python dictionary, which is why I'm thinking submitting it raw as a parameter is the way to go