Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
06-11-2019 07:30 AM
Hi, I want to ask you if there is a way to update just a value of a key in a relationship. I have relationships in my graph where each one has a label "emails_exchanges" and actually my code is:
if graph.match((originLblMatcher, targetLblMatcher), "SEND_MAIL"):
rel = graph.evaluate("MATCH (n:Person {name:\'" + originLbl + "\'})-[r:SEND_MAIL]->(m:Person {name:\'" + targetLbl + "\'}) return r")
count = rel["emails_exchanged"] + 1
graph.create(Relationship(originLblMatcher, "SEND_MAIL", targetLblMatcher, emails_exchanged=count))
else:
emails_exchanged = 1
graph.create(Relationship(originLblMatcher, "SEND_MAIL", targetLblMatcher, emails_exchanged=emails_exchanged))
Is there a method to update just the "email_exchanged" value instead of recreate the entire relationship?
thanks
Solved! Go to Solution.
06-11-2019 11:27 AM
Hello, first of all "emails_exchanges" isn't a label, it's a property key (labels are specific to nodes only, not relationships).
Also it looks like you're using...Python? It helps to tell us what programming language you're using in addition to Cypher, if applicable.
What you're looking for is using SET to set the value of a relationship property, though in this case it would be better to use MERGE on the relationship (which will create it if it doesn't already exist), allowing you to use ON MATCH and ON CREATE to decide what to set depending on if the MERGE matched on existing relationships or instead created a new one between the nodes. You can do this directly through your Cypher:
"MATCH (n:Person {name:\'" + originLbl + "\'}), (m:Person {name:\'" + targetLbl + "\'})
MERGE (n)-[r:SEND_MAIL]->(m)
ON CREATE SET r.emails_exchanged = 1
ON MATCH SET r.emails_exchanged = r.emails_exchanged + 1
RETURN r"
If you expect this to be called concurrently, you may need to use atomic increment proc from APOC Procedures to ensure there are no race conditions between the read and update of the property:
"MATCH (n:Person {name:\'" + originLbl + "\'}), (m:Person {name:\'" + targetLbl + "\'})
MERGE (n)-[r:SEND_MAIL]->(m)
ON CREATE SET r.emails_exchanged = 0
WITH r
CALL apoc.atomic.add(r, 'emails_exchanged', 1) YIELD newValue
RETURN r"
06-11-2019 11:27 AM
Hello, first of all "emails_exchanges" isn't a label, it's a property key (labels are specific to nodes only, not relationships).
Also it looks like you're using...Python? It helps to tell us what programming language you're using in addition to Cypher, if applicable.
What you're looking for is using SET to set the value of a relationship property, though in this case it would be better to use MERGE on the relationship (which will create it if it doesn't already exist), allowing you to use ON MATCH and ON CREATE to decide what to set depending on if the MERGE matched on existing relationships or instead created a new one between the nodes. You can do this directly through your Cypher:
"MATCH (n:Person {name:\'" + originLbl + "\'}), (m:Person {name:\'" + targetLbl + "\'})
MERGE (n)-[r:SEND_MAIL]->(m)
ON CREATE SET r.emails_exchanged = 1
ON MATCH SET r.emails_exchanged = r.emails_exchanged + 1
RETURN r"
If you expect this to be called concurrently, you may need to use atomic increment proc from APOC Procedures to ensure there are no race conditions between the read and update of the property:
"MATCH (n:Person {name:\'" + originLbl + "\'}), (m:Person {name:\'" + targetLbl + "\'})
MERGE (n)-[r:SEND_MAIL]->(m)
ON CREATE SET r.emails_exchanged = 0
WITH r
CALL apoc.atomic.add(r, 'emails_exchanged', 1) YIELD newValue
RETURN r"
06-12-2019 06:48 AM
Thanks for your help. Anyway, yes, I'm using python and py2neo in my application. I have used your solution e it's working perfectly. Sorry for the noob question, but i don't know neo4j and chyper
so well
06-12-2019 10:29 AM
Not a problem, all part of the learning process!
All the sessions of the conference are now available online