我目前正在调查如何在neo4j中建模双时态图。不幸的是,似乎没有人公开承认此事。 我要看的一个特别的事情是,我是否只能在新节点中存储已更改的值,然后表达一个查询,该查询将合并按给定时间戳排序的所有值:
这会创建我正在玩的数据:
CREATE (:P1 {id: '1'})<-[:EXPANDS {date:5200, recorded:5100}]-(:P1Data {name:'Joe', wage: 3000})
// New data, recorded 2014-10-1 for 2015-1-1
MATCH (p:P1 {id: '1'}) CREATE (:P1Data { wage:3100 })-[:EXPANDS { date:5479, recorded: 5387}]->(p)
现在,我可以获得迄今为止给定时间点的历史记录,例如喜欢
MATCH (:P1 { id: '1' })<-[x:EXPANDS]-(d:P1Data)
WHERE x.recorded < 6000
WITH {date: x.date, data:d} as data
RETURN data
ORDER BY data.date DESC
我想要实现的是合并名称和工资值,以便在给定时间点获得数据的完整视图。答案也可能是这不可能。
(PS:我只是在查询中说,因为我在apoc中发现了一个合并节点的重构函数,但是这个程序实际上合并并保留了节点,而我只想查询它)。
答案 0 :(得分:1)
与大多数事情一样,你可以使用REDUCE
这样做:
MATCH (:P1 { id: '1' })<-[x:EXPANDS]-(d:P1Data)
WITH x.date AS date, d AS data
ORDER BY date
WITH COLLECT(data) AS datas
WITH REDUCE(s = {}, y IN datas|
{name: COALESCE(y.name, s.name),
wage: COALESCE(y.wage, s.wage)})
AS most_recent_fields
RETURN most_recent_fields.name AS name, most_recent_fields.wage AS wage
您可以按降序执行此操作(如果是,请在s
语句中交换y
和COALESCE
),但实际上没有办法快捷处理整个集合从您查询的时间回到开始的结果。
更新:当然,这将生成一个Map而不是一个Node,但如果您只想要这些属性而又不想创建一个永久性记录,那么Map实际上更适合您的需求。
EXTENDED:如果您不想指定要使用的密钥,则可以不使用REDUCE
来执行此操作:
MATCH (:P1 { id: '1' })<-[x:EXPANDS]-(d:P1Data)
WITH x.date AS date, d AS data
ORDER BY date
WITH COLLECT(data) AS datas
CREATE (t:Temp)
FOREACH(data IN datas|
SET t += data)
DELETE t
RETURN t
这种方法确实创建了一个节点,但是如果你DELETE
就在它RETURN
之前,它就不会持续存在。 +=
确保不会删除预先存在的属性,只有在data
节点具有现有值时才会覆盖。