cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

How to cypher: Return map instead of list / Set map props within cypher

helpusobi
Node

Hello neo4j people,
this is quite probably a newbie question but I haven't found anything on the subject here/internet.
(With map I mean object (js), dictionary, key/value-pair)
Setup DB: CREATE (n:Node {prop1: 'val1', prop2: 'val2'}).

When one wants a specific subset of the props one can obviously do something like:
UNWIND ['prop1', 'prop2', 'prop3'] as k, MATCH (n:Note) RETURN [k, n[k]]
This shall give the result: [['prop1', 'val1'], ['prop2', 'val2'], ['prop3', null]]
As maps and map accessors are obviously supported I was wondering whether it's possible to also get this result back in a map, so : {prop1: 'val1', prop2: 'val2', prop3: null}.
As it's possible to do something like WITH {a: 'hello'} as map1 RETURN map1 which is {a: 'hello'} I tried to do the following WITH {} as result UNWIND ['prop1', 'prop2', 'prop3'] as k, MATCH (n:Note) SET result[k] = n[k] RETURN k
Unfortunately this doesn't work as SET only works on nodes. I also tried setProperty of apoc: apoc.create.setProperty - APOC Documentation but this also only works on nodes. So I have two questions:

  1. How would one return a map instead of a list naturally in cypher?
  2. When creating a map and accessing maps is both supported in cypher and given that cypher makes apparently no differentiation between accessing a map and accessing a node, how can one set a value in a map?
    Thank you for your time
    Timon
1 ACCEPTED SOLUTION

If you want a map of a defined set of a node's properties, then the following works. It relies on the APOC library. I was not able to figure out getting the data as a map using pure cypher. I could not find a method to dynamically add elements to a map. You can build a map if you know the keys up front, such as:

return {name: n.name, city: n.city}

query using APOC:

with ['prop1', 'prop2', 'prop3'] as keys
match(n) where id(n) = 102
with keys, properties(n) as props
unwind keys as key
with collect(key) as keys, collect(props[key]) as values
return apoc.map.fromLists(keys, values) as map

hope is is what you wanted.

View solution in original post

4 REPLIES 4

glilienfield
Ninja
Ninja

You can use the 'properties' method on a node to get a map of its properties. The props value in the query below will be a map of all node n's properties.

match(n)
return properties(n) as props

If you want a subset of the properties, you can use the map projection syntax. For instance, if you want only properties prop1, prop2, and prop3, you can use the following syntax:

match(n)
with properties(n) as props
return props{ .prop1, .prop2, .prop3}

You can also add your own key/values to the map. Say you want to add a key 'name' and its value is in a variable 'fname', then you can do something like:

match(n)
with properties(n) as props
return props{ .prop1, .prop2, .prop3, name: fname}

if you want to add a variable, such as 'name', and use its name as the key, you can do the following:

match(n)
with properties(n) as props
return props{ .prop1, .prop2, .prop3, name}

If you want all the key/value pairs of a map and add a new key/value, you could do the following:

match(n)
with properties(n) as props
return props{ .*, name}

You can also build a map from scratch as follows:

match(n)
return {id: id(n), key: n.key, name: n.name}

Hello @glilienfield, thank you for your answer. Unfortunately although your answers perfectly satisfy my given questions, they don't satisfy my motivation for this post. But that is my fault as I didn't write my first questions precise enough. My motivation was that given I have a list of unknown entries which represent some keys of the node props how do I retrieve those props:
So given: :param unknownkeys => ['prop1', 'prop3']
And instead of match (n:Node) unwind $unknownkeys as k return [k, n[k]] which works but returns a list, something like match (n:Node) unwind $unknownkeys as k return { [k]: n[k] } (which does not work in cypher). Also somethink like this match (n:Node) unwind $unknownkeys as k return properties(n){[k]} does also not work. So really the question is how to get the props as a map although the keys are not known or simply shall not directly specified in the query?

I can also make a new post of this if that is better.

If you want a map of a defined set of a node's properties, then the following works. It relies on the APOC library. I was not able to figure out getting the data as a map using pure cypher. I could not find a method to dynamically add elements to a map. You can build a map if you know the keys up front, such as:

return {name: n.name, city: n.city}

query using APOC:

with ['prop1', 'prop2', 'prop3'] as keys
match(n) where id(n) = 102
with keys, properties(n) as props
unwind keys as key
with collect(key) as keys, collect(props[key]) as values
return apoc.map.fromLists(keys, values) as map

hope is is what you wanted.

@glilienfield Thank you, that is what I wanted. Have a nice week