gpt4 book ai didi

neo4j - 查找 2 个日期之间的所有事件

转载 作者:行者123 更新时间:2023-12-01 07:29:43 27 4
gpt4 key购买 nike

尝试找出以下场景。

设置:

目标

  • 查找两个日期之间发生的所有事件
  • 查找冲突事件(重叠的事件)

尝试了以下查询:

// Get all events between 2 times
MATCH (m1:Minute { minute: 15 })<--(h:Hour { hour: 8 })<--(d:Day { day: 24 })<--(month:Month { month: 10 })
MATCH (m2:Minute { minute: 45 })<--(h2:Hour { hour: 10 })<--(d2:Day { day: 24 })<--(month2:Month { month: 10 })
MATCH p=((m1)-[:NEXT*]->(m2))
WITH NODES(p) as pnodes UNWIND pnodes AS pwind
MATCH (e:Event)-[:STARTS_AT]->(pwind)
RETURN pwind,e

确实正在检索结果,但注意到:

  1. 如果我尝试使用“最短路径”而不是常规路径,则查询仅适用于特定阈值(奇怪,无法解释这一点)。例如,如果时间跨度超过 2-3 小时,则不起作用;这同样适用于多天等。
  2. 如果不使用“最短路径”,性能会很糟糕。 25 秒内仅返回 2-3 件商品。

使用 where 的另一种变体(仅针对 future 日期尝试):

// Get all events between 2 times
MATCH (e:Event)
WHERE (:Month { month: 10 })-->(:Day { day: 24 })-->(:Hour { hour: 9 })-->(:Minute { minute: 00})-[:NEXT*]->(:Minute)<--(e)
RETURN e

结果:性能甚至更差。 100 秒检索 1 项。

我理解并希望这样做的方式是使用某种允许路径返回相关节点的函数。这是:路径函数仅返回被查询的特定节点(在本例中为分钟),但我想为所有这些分钟带来由“:STARTS_AT”关联的事件。

最后,问题:

  • 执行此查询的推荐方法是什么?
  • 这是 Cypher 和 neo4j 支持的场景吗?
  • “回退”到基于属性的时间查询而不是尝试基于图形的时间查询是否更可取?

提前致谢。

最佳答案

shortestPath 有一个奇怪的地方,如果您没有指定最大长度,它会任意将最大值设置为 15。看这里:

ShortestPath doesn't find any path without max hops limit

我实际上将其称为错误,因为它不在文档中,并且它会导致意外行为,正如您所发现的那样。

所以您的问题的解决方案是使用 shortestPath 但选择最大长度。我会选择非常高的东西;让我们做 10 亿,收工吧:

MATCH (:Year {year:2015})-[:HAS_MONTH]->(:Month {month:10})-[:HAS_DAY]->(:Day {day:23})-[:HAS_HOUR]->(:Hour {hour:8})-[:HAS_MINUTE]->(startMinute:Minute {minute:15})
MATCH (:Year {year:2015})-[:HAS_MONTH]->(:Month {month:10})-[:HAS_DAY]->(:Day {day:24})-[:HAS_HOUR]->(:Hour {hour:10})-[:HAS_MINUTE]->(endMinute:Minute {minute:45})
MATCH p = shortestPath((startMinute)-[:NEXT*..1000000000]->(endMinute))
UNWIND NODES(p) AS minute
MATCH (event:Event)-[:STARTS_AT]->(minute)
RETURN event, minute;

您应该始终使用shortestPath 来查找分钟节点的跨度;在 (startMinute)-[:NEXT*]->(endMinute) 上匹配而不将其包装在 shortestPath 中试图找到两个节点之间任意长度的所有路径,所以它非常详尽并且需要更长的时间,而 shortestPath 可以在找到路径后立即停止。

就查找是否有任何其他事件与特定事件重叠而言:

MATCH (startMinute:Minute)<-[:STARTS_AT]-(event:Event)-[:ENDS_AT]->(endMinute:Minute)
WHERE event.id = {event_id}
MATCH p = shortestPath((startMinute)-[:NEXT*..1000000000]->(endMinute))
UNWIND NODES(p) AS span
MATCH (overlap:Event)-[:STARTS_AT|ENDS_AT]->(span)
WHERE overlap <> event
RETURN overlap;

下面是一个附录,说明如何为概念验证目的创建数据。假设所有月份都有 31 天。

约束和索引。

CREATE CONSTRAINT ON (year:Year) ASSERT year.year IS UNIQUE;
CREATE INDEX ON :Month(month);
CREATE INDEX ON :Day(day);
CREATE INDEX ON :Hour(hour);
CREATE INDEX ON :Minute(minute);

创建时间树。

WITH RANGE(2014, 2015) AS years, RANGE(1, 12) AS months, RANGE(1, 31) AS days, RANGE(0,23) AS hours, RANGE(0, 45, 15) AS minutes
FOREACH(year IN years |
MERGE (y:Year {year: year})
FOREACH(month IN months |
CREATE (m:Month {month: month})
MERGE (y)-[:HAS_MONTH]->(m)
FOREACH(day IN days |
CREATE (d:Day {day: day})
MERGE (m)-[:HAS_DAY]->(d)
FOREACH(hour IN hours |
CREATE (h:Hour {hour: hour})
MERGE (d)-[:HAS_HOUR]->(h)
FOREACH(minute IN minutes |
CREATE (min:Minute {minute: minute})
MERGE (h)-[:HAS_MINUTE]->(min)
)
)
)
)
);

在所有 Minute 节点之间创建 [:NEXT] 关系。

MATCH (year:Year)-[:HAS_MONTH]->(month:Month)-[:HAS_DAY]->(day:Day)-[:HAS_HOUR]->(hour:Hour)-[:HAS_MINUTE]->(minute:Minute)
WITH year, month, day, hour, minute
ORDER BY year.year, month.month, day.day, hour.hour, minute.minute
WITH COLLECT(minute) AS minutes
FOREACH(i IN RANGE(0, LENGTH(minutes) - 2) |
FOREACH(min1 IN [minutes[i]] |
FOREACH(min2 IN [minutes[i + 1]] |
CREATE UNIQUE (min1)-[:NEXT]->(min2)
)
)
);

随机模拟事件及其开始时间。

MATCH (minute:Minute)
WHERE RAND() < 0.3
CREATE (event:Event)-[:STARTS_AT]->(minute);

让所有事件的时长为 5 分钟。

MATCH (event:Event)-[:STARTS_AT]->(startMinute:Minute)-[:NEXT*5]->(endMinute:Minute)
CREATE (event)-[:ENDS_AT]->(endMinute);

关于neo4j - 查找 2 个日期之间的所有事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32685803/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com