获取neo4j中兄弟姐妹中最后创建的东西

问题描述

如何在neo4j 中检索路径中最新节点的列表? disTINCT 运算符似乎没有做我想要的。

一个类似这样的结构:

(n1) - [reln1 cratedAt:"1" something:"not42"] -> ( target )

(n1) - [reln2 cratedAt:"2" something:"42"] -> ( target )

(n2) - [reln3 cratedAt:"1" something:"not42"] -> ( target )

(n2) - [reln4 cratedAt:"3" something:"42"] -> ( target )

(n2) - [reln5 cratedAt:"2" something:"not42"] -> ( target )

问题在于 n1、n2 和目标之间存在未知数量的并行关系(或路径)。

尝试使查询返回具有 rel2 和 rel4 的结构,如下所示,因为 createdAt 分别是来自 n1 和 n2 的最新值。查询应返回:

(n2) - [reln4 cratedAt:"3" something:"42"] -> ( target )
(n1) - [reln2 cratedAt:"2" something:"42"] -> ( target )

在本例中,我正在寻找承载由 something:42 表示的权重的关系或节点。我错过了什么?这不能在一个查询中完成吗?如果它们是节点而不是关系会有所帮助吗?

MATCH (node)-[rel]->(target)
RETURN disTINCT node
ORDER BY rel.createdAt
LIMIT 10

要完成这项工作,我需要先按 createdAt 排序,然后选择最新的,然后每个节点返回一个。怎么样?

编辑:当在关系上创建时,似乎答案对这个结构是有效的 - 但我无法弄清楚如何使用中间节点上的 createdAt 属性将其推广到更长的路径。棘手的问题。

很难概括如下所示的结构:

(O1:Start)-[]-> (mid1:n1 cratedAt:"1" something:"not42") - [reln1 ] -> ( target )

(O1:Start)-[]-> (mid2:n1 cratedAt:"2" something:"42") - [reln2 ] -> ( target )

(O2:Start)-[]-> (mid3:n2 cratedAt:"1" something:"not42") - [reln3 ] -> ( target )

(O2:Start)-[]-> (mid4:n2 cratedAt:"3" something:"42") - [reln4 ] -> ( target )

(O2:Start)-[]-> (mid5:n2 cratedAt:"2" something:"not42") - [reln5 ] -> ( target )

查询应该返回

(O1:Start)-[]-> (mid2:n1 cratedAt:"2" something:"42") - [reln2 ] -> ( target )
(O2:Start)-[]-> (mid4:n2 cratedAt:"3" something:"42") - [reln4 ] -> ( target )

我想要的是标签 n1 和 n2 是兄弟姐妹 - 不仅仅是 rel1 rel2 rel3 等。有没有更好的方法来管理不同来源的重复项,然后查询以找到“正确”的?

解决方法

这是我的答案:

  1. 首先,您需要获取具有最大值的 createdAt 日期
  2. 然后用这个最大值匹配所有节点
  3. 最后返回你想要的节点
MATCH ()-[rel]->()  
WITH  max( rel.cratedAt ) as max_createdAt  
MATCH (node)-[r]->(target) WHERE r.createdAt = max_createdAt 
RETURN node  LIMIT 10
 Result:
 ╒═════════════╕
 │"node"       │
 ╞═════════════╡
 │{"name":"n1"}│
 ├─────────────┤
 │{"name":"n2"}│
 └─────────────┘

编辑:根据用户评论,我更新了下面的答案。

我希望返回整个结构。

 MATCH ()-[rel]->()  
 WITH  max( rel.cratedAt ) as max_createdAt  
 MATCH path=(node)-[r]->(target) WHERE r.cratedAt = max_createdAt 
 RETURN path,type(r) as relationship_name
 LIMIT 10

Result:
 ╒═══════════════════════════════════╤═══════════════════╕
 │"path"                             │"relationship_name"│
 ╞═══════════════════════════════════╪═══════════════════╡
 │[{"name":"n1"},{"cratedAt":"2"},{}]│"reln2"            │
 ├───────────────────────────────────┼───────────────────┤
 │[{"name":"n2"},{}]│"reln4"            │
 └───────────────────────────────────┴───────────────────┘
,

你需要做的是执行你的 MATCH,然后按 rel 的 createdAt 属性排序,然后根据节点和目标收集()关系(所以每个节点和目标,你会得到有序的关系列表),然后获取列表的 head()(它们之间最新创建的 rel)。

你真的应该使用标签,但现在我只会扩展你的密码:

MATCH (node)-[rel]->(target)
WITH node,rel,target
ORDER BY rel.createdAt
WITH node,target,collect(rel) as rels
RETURN node,head(rels) as rel
LIMIT 10

如果使用 Neo4j 4.1.x 或更高版本,那么您可以使用子查询来约束每个节点的扩展和聚合,而不必进行一次大型聚合。这将在您的堆上更容易,因此随着您的图表增长而变得更好:

MATCH (node)
CALL {
 WITH node
 MATCH (node)-[rel]->(target)
 WITH rel,target
 ORDER BY rel.createdAt
 WITH target,collect(rel) as rels
 RETURN target,head(rels) as rel
}
RETURN node,rel
LIMIT 10

(同样,您应该使用标签和 rel 类型,否则必须执行 AllNodesScan,随着图形的增长,性能会很差)。