Two related list merge with unwind or foreach

Hi,
I have three kinds of labeled nodes. User, Post, and Chat. I'm trying to merge some posts belong to a chat. Here's my raw data from REST.

{
  "chatId": "some chat id",
  "posts": [
    {
      "title": "some title",
      "author": {
        "id": 2,
        "name": "john"
      }
    },
    {
      "title": "another title",
      "author": {
        "id": 3,
        "name": "kelly"
      }
    }
  ]
}

I've tried to use unwind to solve the probelm, but unwind two list will get cartesian product, thats not what i want.

MATCH (c:Chat {id: $chatId})
UNWIND $posts AS post
UNWIND $authors AS author
MERGE (p:Post {id: post.id}) SET p += post
MERGE (p)-[:INVOLVED]->(c)
MERGE (u:User {uid: author.uid}) SET u += author
MERGE (u)-[:POSTED]->(p)

Also tried foreach, but the p and u variables seems not getting outside the foreach.

MATCH (c:Chat {id: $chatId})
FOREACH (post in $posts |
	MERGE (p:Post {id: post.id}) SET p += post
)
FOREACH (author in $authors |
	MERGE (u:User {uid: author.uid}) SET u += author
)
WITH p,c,u
MERGE (p)-[:INVOLVED]->(c)
MERGE (u)-[:POSTED]->(p)

Any ideas on how to solve two related list merging?

Hello!

Looking at your raw data, the only list you have is $posts. author seems to be a nested map within each individual post.

Unless you've changed up your data, you should only need a single UNWIND on $posts then use the nested author.

Something like:

MATCH (c:Chat {id: $chatId})
UNWIND $posts AS post
MERGE (p:Post {id: post.id}) 
SET p.title = post.title
MERGE (p)-[:INVOLVED]->(c)
MERGE (u:User {uid: post.author.uid}) 
SET u += post.author
MERGE (u)-[:POSTED]->(p)

Hi @andrew.bowman,
Post has more than one property, say there's 15 of them. In the raw data, I just show one for simplicity. I can't agree more we need only one unwind, but it seems neo4j is not supporting nested properties.

Is there a way to exclude post.author when I'm merging Post. Something like this:

MATCH (c:Chat {id: $chatId})
UNWIND $posts AS post
MERGE (p:Post {id: post.id}) 
SET p = post{excludeProperty: author}

Understood.

Unfortunately out of box we don't have exclusion of elements in a map. You can however do this using APOC Procedures, notably its map functions. After you install the correct version for your Neo4j version, you can do something like:

MATCH (c:Chat {id: $chatId})
UNWIND $posts AS post
WITH post.author as author, apoc.map.removeKey(post, 'author') as post
MERGE (p:Post {id: post.id}) 
SET p = post
...

Thank you very much, I will give it a try in a moment =D