Transitive friendship

Return pairs of users who became friends after a sequence of paiwise transitive friendships between intermediate users.

T-Cypher query:

RANGE_SLICE [2010-01-01T08:01:01Z; 2013-01-01T08:01:01Z] ON R

MATCH (p1:Person) –[PAIR-CONTINUOUS(path:knows*2..7)]->(p2:Person)

RETURN p1, p2, DURATION(path@T)


Interpretation:

In this query, a temporal path of type pairwise-continuous is used to indicate that A became friends with B then B became friends with C while the friendship AB is still valid. The same reasoning holds for relationships BC and CD. A friendship between B and C is first established, and lead to a frienship between C and D.

It can be noticed that Cypher query is more verbose than the original T-Cypher query. That is, the translation consists of decomposing the T-Cypher query into 6 subqueries such as each sub query represents the original query but with a fixed length falling between 2 and 7. Then, each subquery is then translated based on the translation rules of queries with rigid patterns (fixed length).


Cypher query:

MATCH (p1:`Person`)-[r0:`knows`]->(n0)-[r1:`knows`]->(p2:`Person`) WHERE (((myFunctions.min([r0.tEnd, 1357027261000]) – myFunctions.max([r0.tStart, 1262332861000])) > 0 OR (myFunctions.min([r1.tEnd, 1357027261000]) – myFunctions.max([r1.tStart, 1262332861000])) > 0) AND r0.tStart < r1.tStart AND r0.tEnd > r1.tStart AND r0.tEnd < r1.tEnd) RETURN p1, p2, myFunctions.duration([myFunctions.min([r0.tStart, r1.tStart]), myFunctions.max([r0.tEnd, r1.tEnd])]) AS `DURATION(path@T)`

UNION

MATCH (p1:`Person`)-[r0:`knows`]->(n0)-[r1:`knows`]->(n1)-[r2:`knows`]->(p2:`Person`) WHERE (((myFunctions.min([r0.tEnd, 1357027261000]) – myFunctions.max([r0.tStart, 1262332861000])) > 0 OR (myFunctions.min([r1.tEnd, 1357027261000]) – myFunctions.max([r1.tStart, 1262332861000])) > 0 OR (myFunctions.min([r2.tEnd, 1357027261000]) – myFunctions.max([r2.tStart, 1262332861000])) > 0) AND r0.tStart < r1.tStart AND r0.tEnd > r1.tStart AND r0.tEnd < r1.tEnd AND r1.tStart < r2.tStart AND r1.tEnd > r2.tStart AND r1.tEnd < r2.tEnd) RETURN p1, p2, myFunctions.duration([myFunctions.min([r0.tStart, r1.tStart, r2.tStart]), myFunctions.max([r0.tEnd, r1.tEnd, r2.tEnd])]) AS `DURATION(path@T)`

UNION

MATCH (p1:`Person`)-[r0:`knows`]->(n0)-[r1:`knows`]->(n1)-[r2:`knows`]->(n2)-[r3:`knows`]->(p2:`Person`) WHERE (((myFunctions.min([r0.tEnd, 1357027261000]) – myFunctions.max([r0.tStart, 1262332861000])) > 0 OR (myFunctions.min([r1.tEnd, 1357027261000]) – myFunctions.max([r1.tStart, 1262332861000])) > 0 OR (myFunctions.min([r2.tEnd, 1357027261000]) – myFunctions.max([r2.tStart, 1262332861000])) > 0 OR (myFunctions.min([r3.tEnd, 1357027261000]) – myFunctions.max([r3.tStart, 1262332861000])) > 0) AND r0.tStart < r1.tStart AND r0.tEnd > r1.tStart AND r0.tEnd < r1.tEnd AND r1.tStart < r2.tStart AND r1.tEnd > r2.tStart AND r1.tEnd < r2.tEnd AND r2.tStart < r3.tStart AND r2.tEnd > r3.tStart AND r2.tEnd < r3.tEnd) RETURN p1, p2, myFunctions.duration([myFunctions.min([r0.tStart, r1.tStart, r2.tStart, r3.tStart]), myFunctions.max([r0.tEnd, r1.tEnd, r2.tEnd, r3.tEnd])]) AS `DURATION(path@T)`

UNION

MATCH (p1:`Person`)-[r0:`knows`]->(n0)-[r1:`knows`]->(n1)-[r2:`knows`]->(n2)-[r3:`knows`]->(n3)-[r4:`knows`]->(p2:`Person`) WHERE (((myFunctions.min([r0.tEnd, 1357027261000]) – myFunctions.max([r0.tStart, 1262332861000])) > 0 OR (myFunctions.min([r1.tEnd, 1357027261000]) – myFunctions.max([r1.tStart, 1262332861000])) > 0 OR (myFunctions.min([r2.tEnd, 1357027261000]) – myFunctions.max([r2.tStart, 1262332861000])) > 0 OR (myFunctions.min([r3.tEnd, 1357027261000]) – myFunctions.max([r3.tStart, 1262332861000])) > 0 OR (myFunctions.min([r4.tEnd, 1357027261000]) – myFunctions.max([r4.tStart, 1262332861000])) > 0) AND r0.tStart < r1.tStart AND r0.tEnd > r1.tStart AND r0.tEnd < r1.tEnd AND r1.tStart < r2.tStart AND r1.tEnd > r2.tStart AND r1.tEnd < r2.tEnd AND r2.tStart < r3.tStart AND r2.tEnd > r3.tStart AND r2.tEnd < r3.tEnd AND r3.tStart < r4.tStart AND r3.tEnd > r4.tStart AND r3.tEnd < r4.tEnd) RETURN p1, p2, myFunctions.duration([myFunctions.min([r0.tStart, r1.tStart, r2.tStart, r3.tStart, r4.tStart]), myFunctions.max([r0.tEnd, r1.tEnd, r2.tEnd, r3.tEnd, r4.tEnd])]) AS `DURATION(path@T)`

UNION

MATCH (p1:`Person`)-[r0:`knows`]->(n0)-[r1:`knows`]->(n1)-[r2:`knows`]->(n2)-[r3:`knows`]->(n3)-[r4:`knows`]->(n4)-[r5:`knows`]->(p2:`Person`) WHERE (((myFunctions.min([r0.tEnd, 1357027261000]) – myFunctions.max([r0.tStart, 1262332861000])) > 0 OR (myFunctions.min([r1.tEnd, 1357027261000]) – myFunctions.max([r1.tStart, 1262332861000])) > 0 OR (myFunctions.min([r2.tEnd, 1357027261000]) – myFunctions.max([r2.tStart, 1262332861000])) > 0 OR (myFunctions.min([r3.tEnd, 1357027261000]) – myFunctions.max([r3.tStart, 1262332861000])) > 0 OR (myFunctions.min([r4.tEnd, 1357027261000]) – myFunctions.max([r4.tStart, 1262332861000])) > 0 OR (myFunctions.min([r5.tEnd, 1357027261000]) – myFunctions.max([r5.tStart, 1262332861000])) > 0) AND r0.tStart < r1.tStart AND r0.tEnd > r1.tStart AND r0.tEnd < r1.tEnd AND r1.tStart < r2.tStart AND r1.tEnd > r2.tStart AND r1.tEnd < r2.tEnd AND r2.tStart < r3.tStart AND r2.tEnd > r3.tStart AND r2.tEnd < r3.tEnd AND r3.tStart < r4.tStart AND r3.tEnd > r4.tStart AND r3.tEnd < r4.tEnd AND r4.tStart < r5.tStart AND r4.tEnd > r5.tStart AND r4.tEnd < r5.tEnd) RETURN p1, p2, myFunctions.duration([myFunctions.min([r0.tStart, r1.tStart, r2.tStart, r3.tStart, r4.tStart, r5.tStart]), myFunctions.max([r0.tEnd, r1.tEnd, r2.tEnd, r3.tEnd, r4.tEnd, r5.tEnd])]) AS `DURATION(path@T)`

UNION

MATCH (p1:`Person`)-[r0:`knows`]->(n0)-[r1:`knows`]->(n1)-[r2:`knows`]->(n2)-[r3:`knows`]->(n3)-[r4:`knows`]->(n4)-[r5:`knows`]->(n5)-[r6:`knows`]->(p2:`Person`) WHERE (((myFunctions.min([r0.tEnd, 1357027261000]) – myFunctions.max([r0.tStart, 1262332861000])) > 0 OR (myFunctions.min([r1.tEnd, 1357027261000]) – myFunctions.max([r1.tStart, 1262332861000])) > 0 OR (myFunctions.min([r2.tEnd, 1357027261000]) – myFunctions.max([r2.tStart, 1262332861000])) > 0 OR (myFunctions.min([r3.tEnd, 1357027261000]) – myFunctions.max([r3.tStart, 1262332861000])) > 0 OR (myFunctions.min([r4.tEnd, 1357027261000]) – myFunctions.max([r4.tStart, 1262332861000])) > 0 OR (myFunctions.min([r5.tEnd, 1357027261000]) – myFunctions.max([r5.tStart, 1262332861000])) > 0 OR (myFunctions.min([r6.tEnd, 1357027261000]) – myFunctions.max([r6.tStart, 1262332861000])) > 0) AND r0.tStart < r1.tStart AND r0.tEnd > r1.tStart AND r0.tEnd < r1.tEnd AND r1.tStart < r2.tStart AND r1.tEnd > r2.tStart AND r1.tEnd < r2.tEnd AND r2.tStart < r3.tStart AND r2.tEnd > r3.tStart AND r2.tEnd < r3.tEnd AND r3.tStart < r4.tStart AND r3.tEnd > r4.tStart AND r3.tEnd < r4.tEnd AND r4.tStart < r5.tStart AND r4.tEnd > r5.tStart AND r4.tEnd < r5.tEnd AND r5.tStart < r6.tStart AND r5.tEnd > r6.tStart AND r5.tEnd < r6.tEnd) RETURN p1, p2, myFunctions.duration([myFunctions.min([r0.tStart, r1.tStart, r2.tStart, r3.tStart, r4.tStart, r5.tStart, r6.tStart]), myFunctions.max([r0.tEnd, r1.tEnd, r2.tEnd, r3.tEnd, r4.tEnd, r5.tEnd, r6.tEnd])]) AS `DURATION(path@T)`

Comments are closed.