【问题标题】:How to fetch a subgraph of first neighbors in neo4j?如何在neo4j中获取第一个邻居的子图?
【发布时间】:2015-09-18 23:02:07
【问题描述】:

我在 neo4j 中使用此查询获取节点的第一个 n 个邻居: (在本例中,n = 6)

我有一个加权图,所以我也按重量排序结果:

START start_node=node(1859988)
MATCH start_node-[rel]-(neighbor)
RETURN DISTINCT neighbor,
rel.weight AS weight ORDER BY proximity DESC LIMIT 6;

我想获取整个子图,包括第二个邻居(前六个孩子的第一个邻居)。

我试过 smtg 之类的:

START start_node=node(1859988)
MATCH start_node-[rel]-(neighbor)
FOREACH (neighbor | MATCH neighbor-[rel2]-(neighbor2) )
RETURN DISTINCT neighbor1, neighbor2, rel.proximity AS proximity ORDER BY proximity DESC LIMIT 6, rel2.proximity AS proximity ORDER BY proximity DESC LIMIT 6;

语法仍然错误,但我也不确定输出: 我想要一个元组表,父、子和权重: [node_A - node_B - 权重]

我想看看它是执行一个查询还是六个查询更好。 有人可以帮助澄清如何迭代查询(FOREACH)并格式化输出吗?

谢谢!

【问题讨论】:

  • 您熟悉variable length path Cypher 模式吗? (n)-[*1..3]->(m)
  • 是的,它计算从第一个节点(0 包括根节点)到最后一个节点的跳数。所以在我的模式中,每个连接到父母的孩子都是 [*0..1]。

标签: performance neo4j cypher subgraph iterated-function


【解决方案1】:

好的,我想我明白了。这是基于您的评论的另一种尝试:

MATCH (start_node)-[rel]-(neighbor)
WHERE ID(start_node) IN {source_ids}
WITH
  neighbor, rel
ORDER BY rel.proximity
WITH
  collect({neighbor: neighbor, rel: rel})[0..6] AS neighbors_and_rels
UNWIND neighbors_and_rels AS neighbor_and_rel
WITH
  neighbor_and_rel.neighbor AS neighbor,
  neighbor_and_rel.rel AS rel
MATCH neighbor-[rel2]-(neighbor2)
WITH
  neighbor,
  rel,
  neighbor2,
  rel2
ORDER BY rel.proximity
WITH
  neighbor,
  rel,
  collect([neighbor2, rel2])[0..6] AS neighbors_and_rels2
UNWIND neighbors_and_rels2 AS neighbor_and_rel2
RETURN
  neighbor,
  rel,
  neighbor_and_rel2[0] AS neighbor2,
  neighbor_and_rel2[1] AS rel2

有点长,但希望它至少能给你一个想法

【讨论】:

  • 代码返回rel not defined in line 1。我试图打破 - 它不喜欢 ORDER BY rel.proximity 在 collect[] 之后调用:相同的错误“rel 未定义”在这里:MATCH (start_node)-[rel]-(neighbor) WHERE ID(start_node) = 4114904 WITH collect([neighbor, rel])[0..6] AS neighbors_and_rels ORDER BY rel.proximity RETURN neighbors_and_rels; 代码 MATCH (start_node)-[rel]-(neighbor) WHERE ID(start_node) = 4114904 return collect([neighbor, rel])[0..6] AS neighbors_and_rels; 有效,但从概念上讲 ORDER 应该排序 before获取六个孩子[0..6] - 如何对集合进行排序?
  • 啊,对。我已经编辑过,我认为这会奏效。我只是在每个之前添加了一个额外的WITH,它首先进行排序,然后当它们被收集时,它们就会按顺序排列
  • 嗨,快到了,但还没有..Type mismatch: neighbor already defined with conflicting type Map (expected Node) 我认为错误是因为如果上面已经分配了名称,您可能无法分配变量名称AS;我试图确保变量名是不同的,但我仍然有同样的错误。也许neighbor_and_rel[0] AS neighbor 的格式与(node) 类型不同?如果之前的MATCH 中已经存在变量名,您能否澄清一下是否可以重新分配变量名? (例如AS neighborAS rel ..)
  • 好的,我在控制台中运行查询来解析语法并得到同样的错误。我将它重构为使用neighbors_and_rels 的地图,这似乎可以解决它(见编辑)。我想也许当你收集一个包含一个节点的数组时,该节点会被转换为一个地图......
  • 谢谢 ;) 虽然互联网参差不齐,但我们很享受。期待我们在阿根廷的下一站
【解决方案2】:

首先,您应该避免使用 START,因为它(希望)最终会消失。

因此,要获得一个邻域,您可以使用可变长度路径来获取远离节点的所有路径

MATCH path=start_node-[rel*1..3]-(neighbor)
WHERE ID(start_node) = 1859988
RETURN path, nodes(path) AS nodes, EXTRACT(rel IN rels(path) | rel.weight) AS weights;

然后您可以获取路径/节点并将它们与您选择的语言组合在内存中。

编辑:

还可以看看这个 SO 问题:Fetch a tree with Neo4j

它展示了如何将输出作为每个关系的一组开始/结束节点,这在许多情况下可能会更好。

【讨论】:

  • 嗨@Brian,感谢您对输出的建议,但它执行不同的查询:我想为连接到根节点。我也想按重量排序输出。在我的第一个示例中,我能够返回前 6 个关系并为第一次迭代排序(父级 - 前 6 个子级);我不能为每个孩子进行第二次迭代(父母前 6 个孩子 + child_1-first 6 second_children + ...)
  • 我看了看:graphgist.neo4j.com/#!/gists/a5e27b4dca763b6b60a79ac106a52cbb 它提取所有树,我想在每个节点的前 N ​​个节点之间提取树。我试图调整:MATCH p = (o)-[r*0..1]-(x) WHERE ID(o) = 4114904 RETURN collect(DISTINCT id(x)) as nodes, [r in collect(distinct last(r)) | [id(startNode(r)),id(endNode(r)),r.proximity]] as rels 但是:QueryExecutionKernelException:预期 `r@15` 是一个 Collection 但它是一个关系此外,试图找出在哪里插入 ORDER by r.weight 以限制第一个节点上的迭代。
猜你喜欢
  • 2013-04-15
  • 2019-06-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
相关资源
最近更新 更多