I think I am having context issues with calling an apoc procedure, here is my query :
CALL apoc.load.csv("file:///temp/application_biblio/application_biblio.csv", {header:true, sep : '|', ignore:['label', 'examiner', 'examiner_cleaned', 'gau', 'app_type']}) YIELD map as row
MERGE (patent:PATENT {app_num:row.app_num})
with [x IN keys(row) where not x in keys(patent) OR toString(patent[x]) <> row[x]] as keys, patent, row
CALL apoc.do.when(keys is not null,
"
WITH keys, patent, row
CREATE (update:UPDATE_META_BIBLIO)<-[:UPDATED_BIBLIO]-(patent)
FOREACH (x in keys |
SET update.x = patent.x
)
SET patent = apoc.map.clean(row, [], [])
RETURN patent, update
",
"
RETURN patent
"
)
YIELD value
RETURN value
All I wanted to do was to implement a conditional logic in the query that if the keys array is not empty then I want to create a new node and add those items that are present in the keys array to that node.
But I receive the following error :
Neo.ClientError.Procedure.ProcedureCallFailed
Failed to invoke procedure `apoc.do.when`: Caused by: org.neo4j.exceptions.SyntaxException: Variable `keys` not defined (line 2, column 6 (offset: 10))
" WITH keys, patent, row"
^
somehow the keys variable goes out of context (I think)
so can any one explain to me how this works and if there is another simpler way to imply conditional logic in cypher ?
You are trying to access variables outside the scope of the queries executed by the apoc.do.when procedure. The apoc procedure has a parameter ‘param’ that takes a map to pass the values of variables used in the query.
CALL apoc.load.csv("file:///temp/application_biblio/application_biblio.csv", {header:true, sep : '|', ignore:['label', 'examiner', 'examiner_cleaned', 'gau', 'app_type']}) YIELD map as row
MERGE (patent:PATENT {app_num:row.app_num})
with [x IN keys(row) where not x in keys(patent) OR toString(patent[x]) <> row[x]] as keys, patent, row
CALL apoc.do.when(keys is not null,
"
CREATE (update:UPDATE_META_BIBLIO)<-[:UPDATED_BIBLIO]-(patent)
FOREACH (x in keys |
SET update.x = patent.x
)
SET patent = apoc.map.clean(row, [], [])
RETURN patent, update
",
"
RETURN patent
",
{keys: keys, patient: patient, row: row}
)
YIELD value
RETURN value
hey @glilienfield ,
Now the query runs without any errors but for some reason the properties of the update node are not getting setted in the for each loop.
And I have no clue why it is not working. Do you have some suggestion of what might have gone wrong ?
TIA,
Aman
EDIT :
I think the problem is the way I am accessing the values, instead of using . if I use [] then I get the following result :
You use the dot notation to access/set a map property when you know the property name. In your case, you need to dynamically access a map property with the square brackets because your property keys are variables. As such, you can’t perform row.key when key is a variable and not the property ‘key’. Unfortunately, I recall reading a while back that you can’t use the dynamic accessing a property (square brackets) for setting a value.
You could use apoc.create.setProperty or apoc.create.setProperties to set the properties dynamically, as you are trying to do.
A couple observations I made:
I don’t believe the ‘keys’ property can every be null if you csv file is valid. It can be an empty list. As such, I don’t think the ‘else’ query in the apoc.do.when gets executed.
I don’t think your use of apoc.map.clean does anything since both the key and values lists are empty. In affect, you are setting patient equal to row, so you could user ‘set patient = row’ instead
hey @glilienfield ,
Thank you for suggesting the apoc.setproperty it worked.
Apart from that about the observations that you made for the first pointer I wanted to check for the empty list for the keys I will change that to not empty
and for the second pointer I used clean when I wanted to ignore some attributes from the row and then add it to the patent but then I started using ignore in the load csv and I forgot to remove the clean .
Anyways I really thank you for all the help you are giving for the past few days