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.

Updating neo4j relationship properties without duplicating the existing relationship

I have the following

MATCH (a: node)
MATCH (b: node)
MERGE (a) -[c:connect]-> (b)
on match set c.packets_transmitted = 200,
             c.packets_recieved    =350

I want to update the properties without duplicating the relationship which is already exist. Now whenever I run the cypher, the relationship between the nodes connect duplicates. What should I do?

Note: below is the cypher I used to create the relationship connect

MATCH (a:node), (b:node) 
WHERE a.name = sw1 AND b.name = sw2
merge (a)-[:connect {packets_transmitted:0,packets_recieved:0}]->(b)
8 REPLIES 8

Hello @samasamaan

This code should help:

MATCH (a:node)-[c:connect]->(b)
SET c.packets_transmitted = 200, c.packets_recieved = 350

Sorry but it doesn't work. The relationship still duplicates whenever I run the code.
Here is what I did again:

I have the following to first create relationship between nodes (the nodes already created in a previous step)

MATCH (a:node), (b:node) WHERE a.name = 'sw1' AND b.name = 'sw2'
             merge (a)-[c:connect {packets_transmitted:0,packets_recieved:0}]->(b)

Here what I used for updating the relationship properties

MATCH (a:node),(b:node) where a.name='sw1' and b.name ='sw2'
      merge (a)-[c:connect]->(b)
      set c.packets_transmitted = 250,c.packets_recieved = 300

I noticed that whenever the properties values change, a new relationship is created. how can I handle this so that only the properties values are updated without creating a new relationship?
This what I lastly tried and still it duplicates the relationship:

MATCH (a:node), (b:node) 
WHERE a.name = sw1 AND b.name = sw2
merge (a)-[:connect {packets_transmitted:50,packets_recieved:200}]->(b)

MATCH (a:node)-[c:connect]->(b) WHERE a.name = 'sw1' AND b.name = 'sw2'
SET c.packets_transmitted = 200, c.packets_recieved = 350

Can you give me more information about what don't work in the request above, the above request cannot generate more relationships, it doesn't contain any CREATE or MERGE clause to do so.

But the actual duplicates in the database might affect the result.

Also, if you have more than one sw1 and sw2 named nodes, your request will create a cartesian product between all sw1 and sw2 which you might interpret as duplicates.

You don't need to MERGE if you just want to update your existing data.

note: I wrote this code using python.

This is the code for creating the relationship:

cqlCreate=f"MATCH (a:node),(b:node) WHERE a.name ='openflow:2'
 and b.name='2e:38:64:0e:e8:1f'
 merge (a)-[c:connect{{p:0}}]-(b)"

This is the code for update:

cqlUpdate_L=f"MATCH (a:node)-[c:connect]-(b:node) where a.name='openflow:2'
 and b.name='2e:38:64:0e:e8:1f'
 set c.p=10"

This is the entire code which I wrote in python (I modified it to be as clear as possible and still the relationship duplicates)

Note: The code works fine when I execute it directly in neo4j

cqlCreate_1=f"merge(n:node{{name:'openflow:2'}})"
with graphDB_Driver.session() as graphDB_Session:
		graphDB_Session.run(cqlCreate_1)

cqlCreate_3=f"merge(m:node{{name:'2e:38:64:0e:e8:1f'}})"
with graphDB_Driver.session() as graphDB_Session:
		graphDB_Session.run(cqlCreate_3)

cqlCreate_2=f"MATCH (a:node),(b:node) WHERE a.name ='openflow:2'\
and b.name='2e:38:64:0e:e8:1f'\
merge (a)-[c:connect{{p:0}}]-(b)"
with graphDB_Driver.session() as graphDB_Session:
		graphDB_Session.run(cqlCreate_2)

cqlUpdate=f"MATCH (a:node)-[c:connect]-(b:node) where a.name='openflow:2'\
and b.name='2e:38:64:0e:e8:1f'\
set c.p=200"
with graphDB_Driver.session() as graphDB_Session:
	graphDB_Session.run(cqlUpdate)

The answer: No need to establish the relationship property when creating the relationship, since the whole code is executed every time and this leads to relationship duplication. Below is the code after correcting it:

    cqlCreate_1=f"merge(n:node{{name:'openflow:2'}})"
with graphDB_Driver.session() as graphDB_Session:
        graphDB_Session.run(cqlCreate_1)

cqlCreate_3=f"merge(m:node{{name:'2e:38:64:0e:e8:1f'}})"
with graphDB_Driver.session() as graphDB_Session:
        graphDB_Session.run(cqlCreate_3)

cqlCreate_2=f"MATCH (a:node),(b:node) WHERE a.name ='openflow:2'\
and b.name='2e:38:64:0e:e8:1f'\
merge (a)-[c:connect]-(b)"
with graphDB_Driver.session() as graphDB_Session:
        graphDB_Session.run(cqlCreate_2)

cqlUpdate=f"MATCH (a:node)-[c:connect]-(b:node) where a.name='openflow:2'\
and b.name='2e:38:64:0e:e8:1f'\
set c.p=200"
with graphDB_Driver.session() as graphDB_Session:
    graphDB_Session.run(cqlUpdate)

You don't need 2 separate statements as MERGE is similar to upsert.

You can just use this

cqlCreate_2=f"MATCH (a:node),(b:node) WHERE a.name ='openflow:2'\
and b.name='2e:38:64:0e:e8:1f'\
merge (a)-[c:connect]-(b) set c.p=200"
with graphDB_Driver.session() as graphDB_Session:
        graphDB_Session.run(cqlCreate_2)

This will not duplicate the relationship. If it is not there it creates and sets the value. If it already exists it will only update the properties

The cypher will be:

merge (a : node { name : "sw1" } ) -[c : connect]-> (b : node { name : "sw2"}
on match set c.packets_transmitted = 200,
                        c.packets_recieved = 350