# Merge all nodes with the same property name

**URL:** <https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509>\
**Category:** Cypher\
**Created:** [January 21, 2019, 12:43pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509 "2019-01-21T12:43:27Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Joe123](https://avatars.discourse-cdn.com/v4/letter/j/fbc32d/32.png) [@Joe123](https://community.neo4j.com/u/Joe123)\
**Post date:** [January 21, 2019, 12:43pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/1 "2019-01-21T12:43:27Z")

</div>

Hi, I've a problem that I do not know how to code in cypher. I have duplicate nodes with the same property name, (n.name) and they have their own relationships. I wanted to match these nodes, merges the properties and relationships of the 2nd through last nodes onto the first node, and deletes the 2nd through last nodes. I have the code below and it works.

```auto
MATCH (n:name)
WHERE n.name = "john"
WITH COLLECT(n) AS ns
CALL apoc.refactor.mergeNodes(ns) YIELD node
RETURN node;

```

However, I do not want to input the name manually. Is it possible to do a for loop all the nodes that have the same property name and do the above code? like john, jack, jane ...

---

<div class="post-metadata">

**Author:** ![bratanic\_tomaz](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/bratanic_tomaz/32/26823_2.png) [@bratanic\_tomaz](https://community.neo4j.com/u/bratanic_tomaz)\
**Post date:** [January 21, 2019, 2:40pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/2 "2019-01-21T14:40:04Z")

</div>

to find nodes with the same property value

```auto
MATCH (n1:name),(n2:name)
WHERE n1.name = n2.name and id(n1) < id(n2)
WITH [n1,n2] as ns
CALL apoc.refactor.mergeNodes(ns) YIELD node
RETURN node

```

---

<div class="post-metadata">

**Author:** ![Joe123](https://avatars.discourse-cdn.com/v4/letter/j/fbc32d/32.png) [@Joe123](https://community.neo4j.com/u/Joe123)\
**Post date:** [January 21, 2019, 4:05pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/3 "2019-01-21T16:05:16Z")

</div>

> [@bratanic\_tomaz](#):
>
> id(n1) \< id(n2)

id(n1) \< id(n2)  
don't quite get this and got syntax error  
does the id refer to the internal id that neo4j created? i do not have id as property in the node

---

<div class="post-metadata">

**Author:** ![bratanic\_tomaz](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/bratanic_tomaz/32/26823_2.png) [@bratanic\_tomaz](https://community.neo4j.com/u/bratanic_tomaz)\
**Post date:** [January 21, 2019, 4:17pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/4 "2019-01-21T16:17:51Z")

</div>

Yes, this is internal id of Neo4j. I fixed the syntax error

---

<div class="post-metadata">

**Author:** ![Joe123](https://avatars.discourse-cdn.com/v4/letter/j/fbc32d/32.png) [@Joe123](https://community.neo4j.com/u/Joe123)\
**Post date:** [January 21, 2019, 4:37pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/5 "2019-01-21T16:37:08Z")

</div>

works! thanks alot!!!!!

---

<div class="post-metadata">

**Author:** ![i.m](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/i.m/32/3032_2.png) [@i.m](https://community.neo4j.com/u/i.m)\
**Post date:** [January 29, 2019, 6:10am UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/6 "2019-01-29T06:10:38Z")

</div>

Hello, I have actually been looking for a solution like that as well. For me it however leads to a Cartesian product? Is there a way to avoid that?

---

<div class="post-metadata">

**Author:** ![andrew\_bowman](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/andrew_bowman/32/73_2.png) [@andrew\_bowman](https://community.neo4j.com/u/andrew_bowman)\
**Post date:** [January 29, 2019, 6:47am UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/7 "2019-01-29T06:47:49Z")

</div>

Yes, it will look similar to the query in the first post, except we'll collect with respect to name (for each row/name, we'll get the collection of nodes with that name) and filter to only rows where there are multiple nodes for that name:

```auto
MATCH (n:name)
WITH n.name as name, COLLECT(n) AS ns
WHERE size(ns) > 1
CALL apoc.refactor.mergeNodes(ns) YIELD node
RETURN node;

```

---

<div class="post-metadata">

**Author:** ![i.m](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/i.m/32/3032_2.png) [@i.m](https://community.neo4j.com/u/i.m)\
**Post date:** [January 29, 2019, 11:32am UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/8 "2019-01-29T11:32:34Z")

</div>

Brilliant, thanks a lot!!!

---

<div class="post-metadata">

**Author:** ![Joe123](https://avatars.discourse-cdn.com/v4/letter/j/fbc32d/32.png) [@Joe123](https://community.neo4j.com/u/Joe123)\
**Post date:** [March 12, 2019, 2:41am UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/9 "2019-03-12T02:41:00Z")

</div>

Hi, I've an error if the property of my nodes are uniquely indexed. Are there any work around with it?

```auto
New data does not satisfy CONSTRAINT ON ( label[0]:label[0] ) ASSERT label[0].property[0] IS UNIQUE.

```

---

<div class="post-metadata">

**Author:** ![Joe123](https://avatars.discourse-cdn.com/v4/letter/j/fbc32d/32.png) [@Joe123](https://community.neo4j.com/u/Joe123)\
**Post date:** [March 12, 2019, 3:25am UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/10 "2019-03-12T03:25:41Z")

</div>

Nvm solved it using this

```auto
CALL apoc.refactor.mergeNodes(nodes,{properties:"combine", mergeRels:true}) yield node

```

---

<div class="post-metadata">

**Author:** ![katircib](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/katircib/32/7995_2.png) [@katircib](https://community.neo4j.com/u/katircib)\
**Post date:** [December 12, 2019, 6:15pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/11 "2019-12-12T18:15:39Z")

</div>

Hi andrew, is it possible to create case insensitive merge query like this one?

---

<div class="post-metadata">

**Author:** ![andrew\_bowman](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/andrew_bowman/32/73_2.png) [@andrew\_bowman](https://community.neo4j.com/u/andrew_bowman)\
**Post date:** [December 12, 2019, 7:09pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/12 "2019-12-12T19:09:31Z")

</div>

You mean case insensitive on the name property (or the common property used to identify duplicates), or case insensitive on the properties being merged?

If you want case insensitive on the name property, then it should be enough to use toLower() or toUpper() on that property at the time of the collection:

```auto
MATCH (n:name)
WITH toLower(n.name) as name, COLLECT(n) AS ns
WHERE size(ns) > 1
CALL apoc.refactor.mergeNodes(ns) YIELD node
RETURN node;

```

---

<div class="post-metadata">

**Author:** ![katircib](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/katircib/32/7995_2.png) [@katircib](https://community.neo4j.com/u/katircib)\
**Post date:** [December 12, 2019, 7:41pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/14 "2019-12-12T19:41:10Z")

</div>

Worked like a charm, thanks.

---

<div class="post-metadata">

**Author:** ![nwrpub](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/nwrpub/32/5260_2.png) [@nwrpub](https://community.neo4j.com/u/nwrpub)\
**Post date:** [March 8, 2020, 2:39pm UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/15 "2020-03-08T14:39:08Z")

</div>

Hi, I've got a very similar question, but I am unsure on how to solve it.  
I have a pretty big database (\>3 000 000 nodes) and I'm trying to merge nodes but those who have **multiple similar properties** only.

First option works ok, but it's doing a cartesian product, and I fear of running out of memory, or that it will take ages to complete.

I want to use second option, but I don't quite understand how "WITH ... as ... COLLECT" works.  
Is this query correct ?

```auto
MATCH (n:Word) WITH toLower(n.spelling) as spelling AND toLower(n.pos) as pos AND toLower(n.language) as spelling, COLLECT(n) AS ns
WHERE size(ns) > 1
CALL apoc.refactor.mergeNodes(ns) YIELD node
RETURN node;

```

I hope this is an appropriate place to ask my question. Thank you for ur help  
Please excuse my fragile english

---

<div class="post-metadata">

**Author:** ![clem](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/clem/32/4364_2.png) [@clem](https://community.neo4j.com/u/clem)\
**Post date:** [January 9, 2021, 2:32am UTC](https://community.neo4j.com/t/merge-all-nodes-with-the-same-property-name/4509/16 "2021-01-09T02:32:00Z")

</div>

This is my solution that **avoids the Cartesian product**.

The trick is to use `CALL` to force a first `MATCH` to completion without involving a second `MATCH` in a Cartesian Product. This generates the duplicate nodes and a list of the property (names) values of those nodes that have been duplicated. The list of properties that are duplicate makes searching for the duplicates much faster.

The 3rd `MATCH` (outside of the `CALL`) is highly filtered so it's much faster. It gets the two duplicate nodes (that are different because they have different internal `id`'s).

```auto
CALL {MATCH (n:Label)
WITH COLLECT(n.name) AS names // I have to admit I don't know why this works.
WHERE size(names) > 1 
WITH collect(names[0]) as bnames // Makes a list of names that were duplicated but without duplicates
MATCH (b:Label) WHERE b.name in bnames
return b, bnames}
WITH b, bnames // b is duplicate nodes, bnames is list of names that were dupped

// b2 is the node that is a duplicate of b (by name)
MATCH (b2:Label) // get a second node
WHERE b2.name in bnames AND b2.name = b.name AND id(b) > id(b2) // fast match a duplicate
CALL apoc.refactor.mergeNodes([b, b2],
     {properties:"combine", mergeRels:true}) // merging details
YIELD node
RETURN node

```

I'm at the intermediate level, so this query could be improved.... For instance, I suspect that this test isn't needed:

`b2.name in bnames`

Anyway, this query ran faster than the other versions above.

I also Cloned my DB before running the query just in case something went awry...

I hope this helps.
