Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional SET inside ON MATCH of Cypher neo4j

Tags:

neo4j

cypher

Situation in neo4j / cypher.

I have two nodes that represent a person (label), and a relationship between the nodes which is friendship (label). The friendship contains first time they met, last time they met, and things they have done together.

I want to add the nodes if they don’t exist, and if the relationship doesn’t exist too, also add it to the DB.

  • If the friendship didn’t exist, I create it and add the activity they did together and when they met for first time.
  • If the friendship does already exist, I add the activity to the array if it isn’t there already (I don’t want repeated activities). Also update the last time they met.

This is something I want to do in cypher. I have succeeded most of it, however there is something wrong I’m doing. Moreover, if I’m not mistaken, there is no way to compare datetime objects in Cypher so I’m saving the Unix time.

merge (p:Person {name:”Thomas”}) merge (p2:Person {name:”George”}) merge (p)-[r:FRIEND {}]-(p2)

Here I create the things that don’t exist. What if the friendship existed or not?

on create set r.activities = [“eat”], r.firstMeet = 123456, r.lastMeet = 123456

on match set r.activities = r.activities + “play” where not “play” in r.activities, r.lastMeet = 456789 where r.lastMeet < 456789 

Of course that eat, play, 123456. 456789 could be input in some project and this is an example of a query.

The problem is that the cypher makes me problems with the where clausure after set with on match. Maybe it’s not the right way. I have searched a lot, including this website but didn’t find something that could help.

like image 557
Pichi Wuana Avatar asked Sep 11 '25 10:09

Pichi Wuana


1 Answers

Something like this should work:

WITH timestamp() AS datetime
MERGE (p:Person {name: $p1Name})
MERGE (p2:Person {name: $p2Name})
MERGE (p)-[r:FRIEND]-(p2)
ON CREATE SET r.activities = ['eat'], r.firstMeet = datetime, r.lastMeet = datetime
ON MATCH SET
  r.activities = CASE WHEN $activity in r.activities
    THEN r.activities
    ELSE r.activities + $activity END,
  r.lastMeet = datetime;

I assume that you pass in the parameters p1Name, p2Name, and activity, and that it is OK to use the current epoch time (in millisecond units, as generated by the timestamp() function) for your meeting time.

like image 96
cybersam Avatar answered Sep 14 '25 02:09

cybersam