如何在neo4j中处理日期

18

我是一名中世纪历史学家,正在尝试编码1220年至1270年期间(在德国中世纪)各国国王、公爵、教皇之间的网络关系。由于我不是图数据库的专家,因此我正在寻找处理日期和日期范围的可能性。

有没有可能将日期范围传递给边缘,以便表示关系的边缘在例如3年后消失?

有没有可能询问那些具有处于日期范围内的日期标记的关系?

4个回答

13

在Neo4j中处理日期的常见方式是将它们存储为字符串表示或自 Jan 01 1970 起经过的毫秒数 (也称为 epoch 毫秒数)。

第一种方法使图更易读,后者允许您进行数学计算,例如计算时间差。

在您的情况下,我会在关系上存储两个属性,分别称为validFromvalidTo。您的查询需要确保您正在查找正确的时间间隔。

例如,要查找从1220年1月1日到1221年12月31日掌管法国的国王,您可以执行以下操作:

MATCH (c:Country{name:'France'})-[r:HAS_KING]->(king)
WHERE r.validFrom >= -23667123600000 and r.validTo <=-23604051600000
RETURN king, r.validFrom, r.validTo

附录

自 Neo4j 3.0 版本以来,APOC 库提供了几个函数,用于将时间戳转换为/从人类可读的日期字符串。点击此处查看详情。


谢谢您的快速回复。对于我的项目来说,获得良好的可读性和计算增量的可能性非常重要。目前我正在使用类似于“1220-02-05”的iso-data。Neo4j是否有将iso-data转换为毫秒数据的功能? - Andreas Kuczera
很遗憾,目前还没有这样的转换函数。因此您需要在客户端上进行操作。 - Stefan Armbruster
如果你将日期写成"1220-02-05"的格式,就可以在where子句中使用字典序排序。 - J Fabian Meier
1
@StefanArmbruster,你太棒了!我总是从你的回答中获得最有用和精确的信息,今天我只想说声谢谢。长命百岁! - qualebs
使用@DateLong是否推荐? - Sachin Verma
neo4j 3.4 处理日期和时间,详情请参见 https://dev59.com/SV0b5IYBdhLWcg3wT_xr#51175076。 - loopasam

7
您也可以将日期以数字形式存储,格式如下:YYYYMMDD 在您的情况下,12200101表示1220年1月1日,12701231表示1270年12月31日。
这是一种有用且易读的格式,您可以执行范围搜索,例如:
MATCH (h:HistoricEvent)
WHERE h.date >= 12200101 AND h.date < 12701231
RETURN h

如果需要,它还可以让您按日期排序。

3
我会考虑你的提议。你的示例易于理解,可用于计算增量。谢谢。 - Andreas Kuczera
1
你好,我正在尝试使用你的日期类型,但是 neo4j 出现错误:不知道如何进行比较。 左侧:"12230500"(字符串); 右侧:12290225(长整型)-- 有任何想法吗? - Andreas Kuczera
是的@AndreasKuczera,你的第一个对象也应该是 Long。你应该存储 long,并将 long 作为查询参数使用。 - Amin Abu-Taleb
我只是以相同的方式存储所有值:MATCH (from {id:line.id1}), (to {id:line.id2}) create from-[:NEGATIV{reltype:line.rel1, datum:line.date, datenorm:line.datenorm, vorgID:line.vorgID}]->to; 不知道为什么neo4j将一个数字存储为长整型,而将另一个数字存储为字符串。我该如何强制将其存储为长整型? - Andreas Kuczera
该数字已使用datenorm存储。 - Andreas Kuczera

7

从Neo4J 3.4版本开始,系统可以处理时间间隔和日期,详情请查看官方文档。更多示例可在此处查看。

一个与原问题相关的示例:检索过去30天内发生的历史事件:

WITH duration({days: 30}) AS duration
MATCH (h:HistoricEvent)
WHERE date() - duration < date(h.date)
RETURN h

1
是的,3.4版本可以处理日期和空间数据。这是一个非常大的改进! - Andreas Kuczera

1
另一种日期选项可以保持创建的节点/属性数量相对较低,即使用一个链接列表年份(感兴趣的最早年份-最新年份),一个月份(1-12),以及一个月内的日期(1-31)。然后,您图表中的每个“事件”都可以连接到一个年份、月份和日期。这样,您就不必为每个新的年月日组合创建一个新的节点。您只需要一个单独的月份集合、一个日期集合和一个年份集合。我将数字缩放,以使操作更容易,如下所示:
年份为yyyy*10000
月份为mm*100
日期为dd
因此,如果您运行查询,例如:
match (event)-[:happened]->(t:time) 
with event,sum(t.num) as date 
return event.name,date
order by date

你将获得按时间顺序排列的所有事件列表,日期格式为Janurary 17th, 1904出现为19040117 (yyyymmdd格式)。
此外,由于这些是链接列表,例如 ...-(t0:time {num:19040000})-[:precedes]->(t1:time {num:19050000})-... 排序也内置于节点中。
到目前为止,这就是我喜欢进行事件约会的方式。

我正在研究Neo4j中的链表概念,阅读了您的帖子后。但如果您看到这条消息并能发布有关如何实现它的更多详细信息,那将不胜感激! - Nibroc A Rehpotsirhc
当然,您想让我澄清什么? - Tshimanga
我发现了这篇文章...https://neo4j.com/blog/moving-relationships-neo4j/ - Nibroc A Rehpotsirhc
现在,如果您有表示新闻故事的节点(n:Article)和表示公司的节点(m:Company),例如,如果文章发布于20170401,则可以执行以下操作来构造此子图:MATCH (a:Article {title:"some title"}),(c:Company {name:"some company"}) CREATE (a)-[:mentions]->(c) - Tshimanga
然后,您需要执行以下操作来对文章进行日期标记:MATCH (a:Article {title:"some article"}),(y:Year {num:20170000}),(m:Month {num:400}),(d:Date {num:1}) MERGE (y)<-[:published]-(a)-[:published]->(m) merge (a)-[:published]->(d) - Tshimanga
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接