精华 Neo4j官方教程:第15节,日期、日期时间和持续时间
发布于 1 天前 作者 pangguoming 13 次浏览 来自 分享

教程目录 引自:https://neo4j.com/docs/getting-started/cypher-intro/dates-datetimes-durations/

日期、日期时间和持续时间

创建和更新值

让我们首先创建一些具有 Datetime 属性的节点。我们可以通过执行以下 Cypher® 查询来执行此操作:

UNWIND [
    { title: "Cypher Basics I",
      created: datetime("2019-06-01T18:40:32.142+0100"),
      datePublished: date("2019-06-01"),
      readingTime: {minutes: 2, seconds: 15} },
    { title: "Cypher Basics II",
      created: datetime("2019-06-02T10:23:32.122+0100"),
      datePublished: date("2019-06-02"),
      readingTime: {minutes: 2, seconds: 30} },
    { title: "Dates, Datetimes, and Durations in Neo4j",
      created: datetime(),
      datePublished: date(),
      readingTime: {minutes: 3, seconds: 30} }
] AS articleProperties

CREATE (article:Article {title: articleProperties.title})
SET article.created = articleProperties.created,
    article.datePublished = articleProperties.datePublished,
    article.readingTime = duration(articleProperties.readingTime)

在此查询中:

  • created 属性是一个 DateTime 类型,等于执行查询时的时间。
  • date 属性是一个 Date 类型,等于执行查询时的日期。
  • readingTime 是一个 Duration 类型,为 3 分 30 秒。

也许我们想对此文章节点进行一些更改以更新 datePublishedreadingTime 属性。

我们已决定在下周而不是今天发布该文章,因此我们想进行更改。如果我们想使用支持的格式创建一个新的 Date 类型,我们可以使用以下查询来执行此操作:

MATCH (article:Article {title: "Dates, Datetimes, and Durations in Neo4j"})
SET article.datePublished = date("2019-09-30")

但是,如果我们想基于不支持的格式创建 Date 类型怎么办?为此,我们将使用 APOC 库中的函数来解析字符串。

以下查询将不支持的数据格式解析为基于毫秒的时间戳,从该时间戳创建一个 Datetime,然后从该 Datetime 创建一个 Date

WITH apoc.date.parse("Sun, 29 September 2019", "ms", "EEE, dd MMMM yyyy") AS ms
MATCH (article:Article {title: "Dates, Datetimes, and Durations in Neo4j"})
SET article.datePublished = date(datetime({epochmillis: ms}))

我们可以使用相同的方法来更新 created 属性。我们唯一需要更改的是我们不需要将 Datetime 类型转换为 Date

WITH apoc.date.parse("25 September 2019 06:29:39", "ms", "dd MMMM yyyy HH:mm:ss") AS ms
MATCH (article:Article {title: "Dates, Datetimes, and Durations in Neo4j"})
SET article.created = datetime({epochmillis: ms})

也许我们还决定阅读时间实际上将比我们最初想象的要多一分钟。我们可以使用以下查询更新 readingTime 属性:

MATCH (article:Article {title: "Dates, Datetimes, and Durations in Neo4j"})
SET article.readingTime =  article.readingTime + duration({minutes: 1})

格式化值

现在我们要编写一个查询来返回我们的文章。我们可以通过执行以下查询来执行此操作:

MATCH (article:Article)
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

表 1. 结果

title created datePublished readingTime
“Dates, Datetimes, and Durations in Neo4j” 2019-09-25T06:29:39Z 2019-09-29 P0M0DT270S

如果我们想格式化这些值,我们可以使用 APOC 库中的时间函数。以下查询将每个时间类型格式化为更友好的格式:

MATCH (article:Article)
RETURN article.title AS title,
       apoc.temporal.format(article.created, "dd MMMM yyyy HH:mm") AS created,
       apoc.temporal.format(article.datePublished,"dd MMMM yyyy") AS datePublished,
       apoc.temporal.format(article.readingTime, "mm:ss") AS readingTime

表 2. 结果

title created datePublished readingTime
“Dates, Datetimes, and Durations in Neo4j” “25 September 2019 06:29” “29 September 2019” “04:30”

比较和过滤值

如果我们想根据这些时间值过滤我们的文章怎么办?

让我们首先找到 2019 年 6 月 1 日发布的文章。以下查询执行此操作:

MATCH (article:Article)
WHERE article.datePublished = date({year: 2019, month: 6, day: 1})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

表 3. 结果

title created datePublished readingTime
“Cypher Basics I” 2019-06-01T18:40:32.142+01:00 2019-06-01 P0M0DT135S

如果我们想找到 2019 年 6 月发布的所有文章怎么办?我们可以编写以下查询来执行此操作:

MATCH (article:Article)
WHERE article.datePublished = date({year: 2019, month: 6})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

如果我们运行此查询,我们将获得以下结果:

表 4. 结果

title created datePublished readingTime
“Cypher Basics I” 2019-06-01T18:40:32.142+01:00 2019-06-01 P0M0DT135S

这似乎不对 - 2019 年 6 月 2 日发布的 Cypher Basics II 文章呢?我们这里的问题是 date({year: 2019, month:6}) 返回 2019-06-01,所以我们只找到了 2019 年 6 月 1 日发布的文章。

我们需要调整我们的查询以查找 2019 年 6 月 1 日至 2019 年 7 月 1 日之间发布的文章。以下查询执行此操作:

MATCH (article:Article)
WHERE date({year: 2019, month: 7}) > article.datePublished >= date({year: 2019, month: 6})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

表 5. 结果

title created datePublished readingTime
“Cypher Basics I” 2019-06-01T18:40:32.142+01:00 2019-06-01 P0M0DT135S
“Cypher Basics II” 2019-06-02T10:23:32.122+01:00 2019-06-02 P0M0DT150S

如果我们想根据 created 属性(存储 Datetime 值)进行过滤怎么办?我们需要在过滤 Datetime 值时采用与处理 Date 值相同的方法。以下查询查找 2019 年 7 月之后创建的文章:

MATCH (article:Article)
WHERE article.created > datetime({year: 2019, month: 7})
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

表 6. 结果

title created datePublished readingTime
“Dates, Datetimes, and Durations in Neo4j” 2019-09-25T06:04:39.072Z 2019-09-25 P0M0DT210S

最后过滤持续时间。我们可能对可以在 3 分钟或更短时间内阅读的文章感兴趣。

我们将从以下查询开始:

MATCH (article:Article)
WHERE article.readingTime <= duration("PT3M")
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

但是,该查询会导致以下输出:没有更改,没有记录。

如果我们想比较持续时间,我们需要通过将这些持续时间添加到日期来进行比较。我们并不真正关心查询的日期,所以我们将使用当前时间来解决这个问题。我们可以通过调用 datetime() 函数来获取当前时间。

我们更新后的查询如下所示:

MATCH (article:Article)
WHERE datetime() + article.readingTime <= datetime() + duration("PT3M")
RETURN article.title AS title,
       article.created AS created,
       article.datePublished AS datePublished,
       article.readingTime AS readingTime

表 7. 结果

title created datePublished readingTime
“Cypher Basics I” “01 June 2019 18:40” “01 June 2019” “02:15”
“Cypher Basics II” “02 June 2019 10:23” “02 June 2019” “02:30”

资源

本节介绍了如何使用 APOC 库更有效地处理时间类型。以下是有关在 Neo4j 中使用时间类型的更多信息的资源:

  • Cypher 中的时间(日期/时间)值
  • APOC 库
  • 日期和时间转换
  • 时间函数
  • 开发人员博客:Cypher 侦探:处理日期,第 1 部分
回到顶部