1
votes

With following example data:


node1:Person {id: 1, name: 'NameOne'}

node2:Person {id: 2, name: 'NameTwo', age: 42}

question is: if it is possible to standardize properties across all nodes of label Person to the list ['id','name','age','lastname'] so that missing properties are added to the nodes with default empty value and using cypher only?

I have tied using apoc.map.merge({first},{second}) yield value procedure as following:

match (p:Person) 
call apoc.map.merge(proeprties(p),{id:'',name:'',age:'',lastname:''}) yield value 
return value

however I got this error:

There is no procedure with the name apoc.map.merge registered for this database instance. Please ensure you've spelled the procedure name correctly and that the procedure is properly deployed.

although I can confirm I have apoc in place

bash-4.3# ls -al /var/lib/neo4j/plugins/apoc-3.1.0.3-all.jar 
-rw-r--r--    1 root     root       1319762 Dec 14 02:19 /var/lib/neo4j/plugins/apoc-3.1.0.3-all

and it is shown in apoc.help

neo4j-sh (?)$ call apoc.help("map.merge");
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| type       | name                 | text                                                                              | signature                                                 | roles  | writes |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| "function" | "apoc.map.merge"     | "apoc.map.merge(first,second) - merges two maps"                                  | "apoc.map.merge(first :: MAP?, second :: MAP?) :: (MAP?)" | <null> | <null> |
| "function" | "apoc.map.mergeList" | "apoc.map.mergeList([{maps}]) yield value - merges all maps in the list into one" | "apoc.map.mergeList(maps :: LIST? OF MAP?) :: (MAP?)"     | <null> | <null> |
+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
2 rows
47 ms
1

1 Answers

1
votes

Note that these are functions now, so you don't need to call them using CALL or YIELD like procedures. This should work:

match (p:Person) 
RETURN apoc.map.merge(properties(p),{id:'',name:'',age:'',lastname:''})

Keep in mind that this query will only affect what is returned, since you haven't used SET to update the node properties.

You can use the += operator to update a node's properties instead of using apoc.map.merge:

match (p:Person)
set p += {id:'',name:'',age:'',lastname:''}

Keep in mind that both this and apoc.map.merge will replace existing values, so you'll be blanking out id, name, age, and lastname for all persons.

At this time I don't believe there is functionality in Neo4j or APOC to merge in properties while keeping existing properties instead of replacing. That said, there are some workarounds you might use.

COALESCE() is a useful function for this, as it allows you to supply defaults to use in case a value is null.

For example, you might use this to update the properties for all :Persons, using the supplied empty string as a default if the properties are null:

match (p:Person)
with {id:COALESCE(p.id, ''), name:COALESCE(p.name, ''), age:COALESCE(p.age, ''), 
  lastname:COALESCE(p.lastname, '')} as newProps
set p += newProps