3
votes

I have a graph dataset loaded in Neo4j with nodes being various persons and relationships being some "real" relationships between them. What makes it complicated is that each relationship has a time period during which it was valid. For example:

(p1:PERSON {name: "Andy"})
-[r1:HAS_RELATIONSHIP {from: "20190201", to: "20190215"}]->
(p2:PERSON {name: "Betty"})
-[r2:HAS_RELATIONSHIP {from: "20190301", to: "20190331"}]->
(p3:PERSON {name: "Cecil"})

I'd like to take one concrete person P and get a list of all persons with whom P was in an indirect relationship through other persons. It must hold that the intersection of dates in any relationship chain is nonempty.

So from the previous example, if we take Andy as P, the result should be Andy, Betty, because the relationship with Cecil was valid in a completely different period of time. But in the following case:

(p1:PERSON {name: "Andy"})
-[r1:HAS_RELATIONSHIP {from: "20190201", to: "20190215"}]->
(p2:PERSON {name: "Betty"})
-[r2:HAS_RELATIONSHIP {from: "20190210", to: "20190301"}]->
(p3:PERSON {name: "Cecil"})

the result should be Andy, Betty, Cecil.

Is there a way how to specify this condition in Cypher? I'm looking for an efficient solution which prunes the already found paths.

1
Up to what level do you want these indirect relationships?Rajendra Kadam
To an arbitrary level (there is no limit).Kuba Maroušek

1 Answers

1
votes

You basically have a list of intervals from all relationships on a path. For this list of intervals you need to check if they all overlap. This can be done by checking max(from) <= min(to), in cypher:

MATCH path=(p:PERSON {name:'Andy'})-[*..10]-(other) // Doesn't matter how you get the paths
UNWIND relationships(path) as r
WITH path,max(r.from) AS maxFrom,min(r.to) AS minTo
WHERE maxFrom <= minTo
RETURN extract(x in nodes(path) | x.name)