简体   繁体   中英

Query to return nodes that have no specific relationship within an already matched set of nodes

The following statement creates the data I am trying to work with:

CREATE (p:P2 {id: '1', name: 'Arthur'})<-[:EXPANDS {recorded: 1, date:1}]-(:P2Data {wage: 1000})
CREATE (d2:P2Data {wage: 1100})-[:EXPANDS {recorded: 2, date:4}]->(p)
CREATE (d3:P2Data {wage: 1150})-[:EXPANDS {recorded: 3, date:3}]->(p)
CREATE (d3)-[:CANCELS]->(d2)

So, Arthur is created and initially has a wage of 1000. On day 2 we add the info that the Wage will be 1100 from day 4 onwards. On day 3 we state that the wage will be increased to 1150 , which cancels the entry from day 2.

Now, if I look at the history as it was valid for a given point in time, when the point in time is 2, the following history is correct:

  • day 1 - wage 1000
  • day 4 - wage 1100

when the point in time is 3, the following history is correct:

  • day 1 - wage 1000
  • day 3 - wage 1150

expressed in graph terms, when I match the P2Data based on the :EXPANDS relationship, I need those that are not cancelled by any other P2Data node that has also been matched .

This is my attempt so far:

MATCH p=(:P2 {id: '1'})<-[x1:EXPANDS]-(d1:P2Data)
WHERE x1.recorded <= 3
WITH x1.date as date, 
FILTER(n in nodes(p) 
  WHERE n:P2Data AND 
  SIZE(FILTER(n2 IN nodes(p) WHERE (n2:P2Data)-[:CANCELS]->(n))) = 0) AS result
RETURN date, result

The idea was to only get those n in nodes(p) where there are no paths pointing to it via the :CANCELS relationship.

Since I am still new to this and somehow cypher hasn't clicked yet for me, feel free to discard that query completely.

MATCH (:P2 {id: '1'})<-[x1:EXPANDS]-(d1:P2Data)
WHERE x1.recorded <= 3
WITH x1.date AS valid_date, x1.recorded AS transaction_date, d1.wage AS wage
ORDER BY valid_date
WITH COLLECT({v: valid_date, t: transaction_date, w:wage}) AS dates
WITH REDUCE(x = [HEAD(dates)], date IN TAIL(dates)|
    CASE
    WHEN date.v = LAST(x).v AND date.t > LAST(x).t THEN x[..-1] + [date]
    WHEN date.t > LAST(x).t THEN x + [date]
    ELSE x 
    END) AS results
UNWIND results AS result
RETURN result.v, result.w

I'm trying to think of a way to model this better, but I'm honestly pretty stumped.

If you modify your data model by removing the CANCELS relationship, and instead add an optional canceled date to the EXPANDS relationship type, you can greatly simplify the required query.

For example, create the test data:

CREATE (p:P2 {id: '1', name: 'Arthur'})<-[:EXPANDS {recorded: 1, date:1}]-(:P2Data {wage: 1000})
CREATE (d2:P2Data {wage: 1100})-[:EXPANDS {recorded: 2, date:4, canceled: 3}]->(p)
CREATE (d3:P2Data {wage: 1150})-[:EXPANDS {recorded: 3, date:3}]->(p)

Perform simple query:

MATCH p=(:P2 {id: '1'})<-[x1:EXPANDS]-(d1:P2Data)
WHERE x1.recorded <= 3 AND (x1.canceled IS NULL OR x1.canceled > 3)
RETURN x1.date AS date, d1
ORDER BY date;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM