# Deleting nodes related to specific node and then adding nodes again

**URL:** <https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586>\
**Category:** Cypher\
**Tags:** cypher\
**Created:** [February 11, 2020, 2:29pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586 "2020-02-11T14:29:09Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![timojannejokine](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/timojannejokine/32/8414_2.png) [@timojannejokine](https://community.neo4j.com/u/timojannejokine)\
**Post date:** [February 11, 2020, 2:29pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/1 "2020-02-11T14:29:09Z")

</div>

Hi, I can't tell what is wrong with my query.  
I have a node (KnowledgeEntry) that has an outgoing 'CONTAINS' relationship to multiple nodes of type KnowledgeRecord. The query is used to update a KnowledgeEntry and its Records.

Firstly, I want to set the new KnowledgeEntry values which works perfectly fine. Then I want to delete all KnowledgeRecord nodes that are connected to the KnowledgeEntry.

Then I loop over the new Records and create them and add them to the KnowledgeEntry.

If I run the delete query solely it works perfectly fine. But when I re-add the new KnowledgeRecords in the same query the old KnowledgeRecords won't be deleted. I cannot figure out how to accomplish what I'm trying to do. Do I need to run two separate queries?

Here's my query:

```auto
MATCH (knowledgeEntry:KnowledgeEntry) WHERE knowledgeEntry.id = $id

SET knowledgeEntry += {
  title: $knowledgeEntry.title
}

/* Here I delete all knowledgeRecords connected to the knowledgeEntry */
WITH knowledgeEntry
OPTIONAL MATCH (knowledgeEntry)-[rel:CONTAINS]->(rec:KnowledgeRecord)
DETACH DELETE rel

/* Here I re-add the new knowledgeRecords */
WITH knowledgeEntry
UNWIND $knowledgeRecords AS record
CREATE (knowledgeRecord:KnowledgeRecord)
SET knowledgeRecord = record
CREATE (knowledgeEntry)-[:CONTAINS]->(knowledgeRecord)

RETURN knowledgeEntry, collect(knowledgeRecord) AS knowledgeRecords;

```

---

<div class="post-metadata">

**Author:** ![tony.chiboucas](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/tony.chiboucas/32/5980_2.png) [@tony.chiboucas](https://community.neo4j.com/u/tony.chiboucas)\
**Post date:** [February 11, 2020, 3:36pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/2 "2020-02-11T15:36:01Z")

</div>

If you want to delete the Records: `DETACH DELETE rec`  
If you want to keep the Records, but delete the rel between Entry and Record: `DELETE rel`

If I assume you want to delete the Records:

```auto
WITH knowledgeEntry
OPTIONAL MATCH (knowledgeEntry)-[rel:CONTAINS]->(rec:KnowledgeRecord)
DETACH DELETE rec

WITH knowledgeEntry
UNWIND $knowledgeRecords AS record
CREATE (knowledgeRecord:KnowledgeRecord)
SET knowledgeRecord = record
CREATE (knowledgeEntry)-[:CONTAINS]->(knowledgeRecord)

```

If you're trying to delete the relationships, the second WITH may be preventing that. So, temporarily mutate the graph.

```auto
WITH knowledgeEntry
OPTIONAL MATCH (knowledgeEntry)-[rel:CONTAINS]->(rec:KnowledgeRecord)
SET rel.deleteme = 1

WITH knowledgeEntry
UNWIND $knowledgeRecords AS record
CREATE (knowledgeRecord:KnowledgeRecord)
SET knowledgeRecord = record
CREATE (knowledgeEntry)-[:CONTAINS]->(knowledgeRecord)

WITH knowledgeEntry
MATCH (knowledgeEntry)-[rel:CONTAINS {deleteme: 1}]->()
DELETE rel

```

---

<div class="post-metadata">

**Author:** ![timojannejokine](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/timojannejokine/32/8414_2.png) [@timojannejokine](https://community.neo4j.com/u/timojannejokine)\
**Post date:** [February 11, 2020, 6:50pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/3 "2020-02-11T18:50:54Z")

</div>

I want to delete the Records and add the new ones ($knowledgeRecords param represents the new ones)

With the first query you provided the result doesn't change unfortunately.  
Actually, every time I run this query the amount of knowledgeRecords that are already connected is multiplied by the length of $knowledgeRecords param.

So if the Entry had two records and I want to replace them with three new records the result is a Entry node with six record nodes.  
If the Entry has six record nodes and I want to replace them with five new records the result is a Entry node with 30 record nodes.

Could this be a bug???

---

<div class="post-metadata">

**Author:** ![tony.chiboucas](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/tony.chiboucas/32/5980_2.png) [@tony.chiboucas](https://community.neo4j.com/u/tony.chiboucas)\
**Post date:** [February 11, 2020, 8:05pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/4 "2020-02-11T20:05:16Z")

</div>

> [@timojannejokine](#):
>
> ```auto
> MATCH (knowledgeEntry:KnowledgeEntry) WHERE knowledgeEntry.id = $id
> 
> SET knowledgeEntry += {
> title: $knowledgeEntry.title
> }
> 
> ```

More likely something odd going on with your `id` and this `MATCH` clause.

How are you populating the `$id`, `$knowledgeEntry`, and `$knowledgeRecords` parameters?

---

<div class="post-metadata">

**Author:** ![timojannejokine](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/timojannejokine/32/8414_2.png) [@timojannejokine](https://community.neo4j.com/u/timojannejokine)\
**Post date:** [February 11, 2020, 8:17pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/5 "2020-02-11T20:17:02Z")

</div>

I'm using the java bolt driver api

The params object is a Map:  
`Map<String, Object>`  
and it looks like this:

```auto
Map.of("id", id, "knowledgeEntry", knowledgeEntry, "knowledgeRecords", records),

```

When debugging those are my values:

- id is a String
- knowledgeEntry is a `Map<String, Object>` with only one entry so far: `String title`
- knowledgeRecords is a `List<Map<String, Object>>` and each of the entries has the following properties:  
`String content`  
`String type`  
`Integer order`

```auto
try (Session session = driver.session()) {
    return session.writeTransaction(transaction -> transaction.run(cypher, params).stream()
        .map(function)
        .collect(Collectors.toList()));
 }

```

KnowledgeEntry and KnowledgeRecords are basically my domain classes converted to a map / list of maps.  
Also, i dont know if it is important but in both types of map objects there are some null values.

---

<div class="post-metadata">

**Author:** ![tony.chiboucas](https://sea1.discourse-cdn.com/flex021/user_avatar/community.neo4j.com/tony.chiboucas/32/5980_2.png) [@tony.chiboucas](https://community.neo4j.com/u/tony.chiboucas)\
**Post date:** [February 11, 2020, 9:18pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/6 "2020-02-11T21:18:31Z")

</div>

There's enough going on here that the nulls _might_ have some side-effects, but I doubt it. Nothing is deleted until the transaction is complete, so there might be some conflict with that, and your `CREATE (knowledgeRecord:KnowledgeRecord)` of a new blank node of the same label. You might want to delete in one command, and create in another.

That said, a little deformation of the graph, and doing the delete at the end, might work. Give it a try.

Avoid duplicate nodes with constraints:

```auto
CREATE CONSTRAINT ON (e::KnowledgeEntry) ASSERT e.id IS UNIQUE

```

**Duplicates out of the way - deform, create, delete:**  
Avoid `OPTIONAL MATCH` here, you don't need to delete something that isn't there.

```auto
MATCH (e:KnowledgeEntry {id: $id})
SET e.title = $knowledgeEntry.title

WITH e
MATCH (e)-[rel:CONTAINS]->(rec:KnowledgeRecord)
SET rec.deleteMe = 1

WITH e
UNWIND $knowledgeRecords AS record
CREATE (r:KnowledgeRecord)<-[:CONTAINS]-(e)
SET r = record

MATCH (deleteRecord:KnowledgeRecord {deleteMe: 1})
DETACH DELETE deleteRecord

```

---

<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:** [February 12, 2020, 7:18pm UTC](https://community.neo4j.com/t/deleting-nodes-related-to-specific-node-and-then-adding-nodes-again/14586/7 "2020-02-12T19:18:52Z")

</div>

> [@timojannejokine](#):
>
> Here's my query:
> 
> ```auto
> MATCH (knowledgeEntry:KnowledgeEntry) WHERE knowledgeEntry.id = $id
> 
> SET knowledgeEntry += {
> title: $knowledgeEntry.title
> }
> 
> /* Here I delete all knowledgeRecords connected to the knowledgeEntry */
> WITH knowledgeEntry
> OPTIONAL MATCH (knowledgeEntry)-[rel:CONTAINS]->(rec:KnowledgeRecord)
> DETACH DELETE rel
> 
> /* Here I re-add the new knowledgeRecords */
> WITH knowledgeEntry
> UNWIND $knowledgeRecords AS record
> CREATE (knowledgeRecord:KnowledgeRecord)
> SET knowledgeRecord = record
> CREATE (knowledgeEntry)-[:CONTAINS]->(knowledgeRecord)
> 
> RETURN knowledgeEntry, collect(knowledgeRecord) AS knowledgeRecords;
> 
> ```

The query itself almost looks fine (though per the discussion, if you want to delete the connected :KnowledgeRecord nodes rather than the relationship between the nodes, you'll want to change which variable you're using for the DETACH DELETE), but you will need to reset the cardinality before you create the new records.

That is, for a specific knowledgeEntry, if there were 5 connected recs to delete, you would still have 5 rows for that knowledgeEntry going into the create part of the query, multiplying the number of nodes created and relationships made. `WITH knowledgeEntry` doesn't reset cardinality or deduplicate rows.

You would either need to reset the cardinality with an aggregation or DISTINCT:

```auto
WITH knowledgeEntry, count(knowledgeEntry) as ignore

```

or

```auto
WITH DISTINCT knowledgeEntry

```

You may want to PROFILE a run of this query to see what it's doing. Also, check the id() of the connected nodes before and after this query. If the id()s of the rec nodes before the execution of the query are no longer present in the graph after, then they are getting deleted properly, and something else is going on.
