【问题标题】:How to handle dates in neo4j如何在 neo4j 中处理日期
【发布时间】:2015-06-03 07:47:00
【问题描述】:

我是一位研究中世纪历史的历史学家,我正在尝试编写中世纪德国约 50 年(从 1220 年到 1270 年)期间国王、公爵、教皇等之间的网络。由于我不是图形数据库专家,我正在寻找一种处理日期和日期范围的可能性。

是否有可能在日期范围内处理边缘,以便表示关系的边缘在例如3 年?

是否有可能要求在日期范围内具有日期标签的关系?

【问题讨论】:

    标签: date neo4j date-range


    【解决方案1】:

    在 Neo4j 中处理日期的常用方法是将它们存储为字符串表示形式或自纪元以来的毫秒(即自 1970 年 1 月 1 日以来经过的毫秒)。

    第一种方法使图表更易于阅读,后者允许您进行数学运算,例如计算增量。

    在您的情况下,我将在关系上存储两个名为 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 库提供了couple of functions for converting timestamps to/from human readable date strings

    【讨论】:

    • 感谢您的快速回答。对于我的项目,获得良好的可读性和计算增量的可能性很重要。目前我正在使用像“1220-02-05”这样的iso数据。 neo4j 是否具有将 iso-Data 转换为毫秒数据的功能?
    • 很遗憾这样的转换功能还不存在。所以你需要在客户端做。
    • @AndreasKuczera 如果您将日期写为“1220-02-05”,则可以在 where 子句中使用字典顺序。
    • @StefanArmbruster 你太棒了!我总是从您提供的几乎所有答案中获得最有用和最准确的信息,今天我只想说声谢谢。万岁!
    • 是否推荐使用@DateLong?
    【解决方案2】:

    您还可以将日期存储在数字表示中,格式如下:YYYYMMDD

    在您的情况下,12200101 将是 1220 年 1 月 1 日,12701231 将是 1270 年 12 月 31 日。

    这是一种有用且可读的格式,您可以执行范围搜索,例如:

    MATCH (h:HistoricEvent)
    WHERE h.date >= 12200101 AND h.date < 12701231
    RETURN h
    

    如果需要,它还可以让您按日期订购。

    【讨论】:

    • 我会考虑你的提议。您的示例是人类可读的,可用于增量计算。谢谢。
    • 您好,我正在尝试您的日期类型,但 neo4j 出现错误:不知道如何比较。左:“12230500”(字符串);右:12290225(长)——有什么想法吗?
    • 是的@AndreasKuczera,您的第一个对象也应该是 Long。您应该存储 longs 并将 longs 用作查询的参数
    • 我只是以相同的方式存储所有值:MATCH (from {id:line.id1}), (to {id:line.id2}) create from-[:NEGATIV{reltype:line.rel1, datum:line.date, datenorm:line.datenorm, vorgID:line.vorgID}]-&gt;to; 不知道为什么 neo4j 存储一个数字和另一个数字一样长。我怎样才能强制存储多久?
    • 数字以datenorm存储。
    【解决方案3】:

    另一个使您创建的节点/属性数量保持在较低水平的日期选项是链表年份(感兴趣的最早年份 - 最近年份)、月份之一 (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
    

    您将获得按时间顺序排列的所有事件列表,日期如 1904 年 1 月 17 日显示为 19040117(yyyymmdd 格式)

    此外,因为这些是链表,例如, ...-(t0:time {num:19040000})-[:precedes]->(t1:time {num:19050000})-... 排序也内置在节点中。

    到目前为止,这是我喜欢的约会方式

    【讨论】:

    • 在阅读了您的帖子后,我正在尝试研究 Neo4j 中链表的概念,但如果您看到此内容并可以发布有关如何实现此功能的更多详细信息,将不胜感激!跨度>
    • 当然,您希望我澄清什么?
    • 我找到了这篇文章...neo4j.com/blog/moving-relationships-neo4j
    • 我用它作为基础创建了几个月的链表,但是,当按照本文中的说明进行操作时,我的“NEXT”关系没有标记为下一个,而是用 ID 标记的关系。也许这无关紧要。在我的图表数据库中,我有新闻故事和公司的节点,它们具有 MENTIONS 关系来指示哪些商店提到了公司。我还想与文章撰写日期建立关系。那么,我的年、月、日链接列表如何协同工作以与每个故事相关,这是我还无法理解的。谢谢!
    • 嗯,略读了这篇文章,它似乎与您的需求相切,除非您需要能够通过链接列表传播关系。一般来说,链表在理论上和您的特定用例中稍微简单一些。首先,列表标识符节点不是完全必要的,因为节点标签可以达到相同的效果。
    【解决方案4】:

    As of Neo4J 3.4,系统处理持续时间和日期,参见official documentation。查看更多示例here

    与原始问题相关的示例:检索从现在起最近 30 天内发生的历史事件:

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

    【讨论】:

    • 是的,3.4 可以处理日期和空间数据。很大的进步!
    猜你喜欢
    • 1970-01-01
    • 2013-11-22
    • 1970-01-01
    • 2014-01-14
    • 1970-01-01
    • 1970-01-01
    • 2014-09-17
    • 1970-01-01
    • 2015-11-28
    相关资源
    最近更新 更多