Greetings to all lovers of graphs and especially neo4j and cypher.
I am currently working on a project and a problem has arisen. I am creating the fake data of the graph which I am filling from python.
I have my UserApp label nodes with an idn property that plays the role of a numeric id and I have a dateTimeSignin name property with a value in the format: "2004-02-06T13:13:39.923148", this property plays the role of storing the time the user logged into the system.
So my problem comes when creating a friend relationship where I have to have a name property: fromThisMoment, this property will record the moment they became friends. This value has to be less than the current time the script is executed and greater than the dateTimeSignin of the two users.
For this, in my code I executed this code and I have varied it several times but it gives me an error:
def insertar(ruta):
conn.query_insert("""
CALL apoc.load.json("file:///{ruta}")
YIELD value AS row
CALL{{
with row
MATCH (u:UserApp {{idn: row.usuario_id}})
MATCH (f:UserApp {{idn: row.friend_id}})
MERGE (u)-[:FRIEND_OF]->(f)
}}""".format(ruta=ruta))
This is my relationship creation code which reads a .json file and tried several ways but I have not been able to establish a random date in the range of being less than the current moment and greater than the dateTimeSignin of the two users in the relationship.
Here's an example of pure Cypher generating a random date between now and a week ago, breaking down each step:
WITH datetime.realtime() as now
WITH now, now - duration({days: 7}) as lastWeek
WITH now, lastWeek, duration.inSeconds(lastWeek, now) as maxSeconds
WITH now, lastWeek, maxSeconds, round(rand() * maxSeconds.seconds) as offset
WITH now, lastWeek, maxSeconds, offset, lastWeek + duration({seconds:offset}) as inbetweenDate
RETURN now, lastWeek, maxSeconds.seconds, offset, inbetweenDate
This calculates the duration in seconds between the boundary dates, then creates a random offset of seconds from the lower boundary, finally creating an inbetweenDate by adding the offset to the lower boundary.
As a solution I adopted a random date of the last two years, but I would like to have a random in the range of the current date to the date of the user registration.
I attach my resulting code
MATCH (u1:UserApp)-[r:FOLLOWS]->(u2:UserApp)
WITH r, datetime.realtime() as now
WITH r, now, now - duration({days: 729}) as lastYear
WITH r, now, lastYear, duration.inSeconds(lastYear, now) as maxSeconds
WITH r, now, lastYear, maxSeconds, round(rand() * maxSeconds.seconds) as offset
WITH r, now, lastYear, offset, lastYear + duration({seconds:offset}) as inbetweenDate
SET r.fromThisMoment = inbetweenDate
Assuming that dateTimeSignin is a string, you could parse that for the lower bounds, then use half the duration to get the in-between date...
WITH "2004-02-06T13:13:39.923148" as dateTimeSignin
WITH datetime.realtime() as now, datetime(dateTimeSignin) as lowerBounds
WITH now, lowerBounds, duration.inSeconds(lowerBounds, now) as durationInSeconds
WITH now, lowerBounds, durationInSeconds, durationInSeconds.seconds / 2 as offset
WITH now, lowerBounds, durationInSeconds, offset, lowerBounds + duration({seconds:offset}) as inbetweenDate
RETURN now, lowerBounds, offset, inbetweenDate