cancel
Showing results for 
Search instead for 
Did you mean: 

Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.

Cypher return structured map

q6qgs
Node Link

is it possible to return an object of objects (each key containing an object)?

what I want to achieve:

 {
     a1 : { name: "bob", age: 45 }, 
     a2 : { name: "toby", age: 27 }
 }

or

 [
   a1 : { name: "bob", age: 45 }, 
   a2 : { name: "toby", age: 27 }
 ]

my statement:

MATCH (n:User)
WITH n.id AS key, {name:n.name, age:n.age}AS value
RETURN collect({key:value})
1 ACCEPTED SOLUTION

You are really really close. I think all you need is apoc.map.fromPairs which takes an array of key value pairs and turns them into a map. For example, if you have data like this:

RETURN apoc.map.fromPairs([ ["a", "b"], ["c", "d"] ])

Then you get:

{
  "a": "b",
  "c": "d"
}

So your "values" are nested maps, but that's no problem. If you change your query to this:

match (n:User) 
with n.id as key, { name: n.name, age: n.age } as value 
return apoc.map.fromPairs(collect([key, value]));

I think you'll get what you want.

Note that you can't do this:

{ key: value }

Because in this case cypher interprets "key" as literally the text key, not as the content of whatever that variable is.

View solution in original post

2 REPLIES 2

You are really really close. I think all you need is apoc.map.fromPairs which takes an array of key value pairs and turns them into a map. For example, if you have data like this:

RETURN apoc.map.fromPairs([ ["a", "b"], ["c", "d"] ])

Then you get:

{
  "a": "b",
  "c": "d"
}

So your "values" are nested maps, but that's no problem. If you change your query to this:

match (n:User) 
with n.id as key, { name: n.name, age: n.age } as value 
return apoc.map.fromPairs(collect([key, value]));

I think you'll get what you want.

Note that you can't do this:

{ key: value }

Because in this case cypher interprets "key" as literally the text key, not as the content of whatever that variable is.

christian
Node Clone

@david.allen thanks for the above solution mate, much appreciated. I've tried to adopt it to my problem but am turning in circles and it is driving me mad ... would you please take a quick look at the below and let me know what I'm doing wrong?

Desired output ...

{
  "JobWords": {
    {
      "IdInterface": "leader",
      "NameInterfaceLower": "leader",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_leader"
    },
    {
      "IdInterface": "founder",
      "NameInterfaceLower": "founder",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_founder"
    },
    {
      "IdInterface": "marketing",
      "NameInterfaceLower": "marketing",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_marketing"
    },
    {
      "IdInterface": "measurement",
      "NameInterfaceLower": "measurement",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_measurement"
    }
  }
}

But the Cypher I am using ...

MATCH (Employee:Employee{IdObject:'xyz'}) 
WITH Employee 

OPTIONAL MATCH (Employee)-[:LINKED_TO]->(:EmailAddress:Master)<-[:CONTAINED_IN|CONNECTED_TO]-(n:JobWord) 
WHERE NOT n:Exclude 
WITH Employee, n.IdUnique as key, {IdInterface: n.IdInterface, NameInterfaceLower: n.NameInterfaceLower, NameInterfaceOriginal: n.NameInterfaceOriginal, IdInterfaceTag: n.IdInterfaceTag} as value 
WITH Employee, apoc.map.fromPairs(collect([key, value])) as job_words 

RETURN 
Employee {

    JobWords: job_words
}

Only ever returns ...

{
  "JobWords": {
    "3e9ce5c6-6344-4cff-a80f-d4f7708e8e26": {
      "IdInterface": "leader",
      "NameInterfaceLower": "leader",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_leader"
    },
    "862ce5d8-651c-424b-b0c9-313c500ea266": {
      "IdInterface": "founder",
      "NameInterfaceLower": "founder",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_founder"
    },
    "4d1a76d7-44ba-462f-847b-5118599532bf": {
      "IdInterface": "marketing",
      "NameInterfaceLower": "marketing",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_marketing"
    },
    "373d5ec0-085b-4202-9631-a3c4585dd45c": {
      "IdInterface": "measurement",
      "NameInterfaceLower": "measurement",
      "NameInterfaceOriginal": null,
      "IdInterfaceTag": "job+word_measurement"
    }
  }
}

I've tried everything to get a list from just pairs without the nested part but no luck 😞 I must be missing something super obvious and simply cannot see it ...