使用 Cypher 以递增的关系权重顺序遍历 Neo4j 图
Traversing Neo4j graph in increasing order of relationship weights using Cypher
考虑一下我有以下带有边权重的图表:
我想知道我是否可以使用 CYPHER 执行从节点 a 开始的遍历,然后按照权重的递增顺序执行遍历。也就是上面应该return(a)-4->(e)-3->(c)-3->(d)
这可以使用密码吗?
您的描述略有错误(根据您的示例),因为您不想遍历具有增加权重的关系,您想要遍历关系每一步的 最大 权重。
您不能在 Cypher 中以通用方式执行此操作,因为结果是迭代构建的,并且您无法知道结果路径的最大长度。
在 Cypher 中,您必须
- 构建所有路径
- 按第一个关系的权重过滤它们
- 通过第二个关系的权重过滤剩余的(如果存在)
- 等等
Cypher 的声明性本质并不真正兼容:它会很麻烦,而且可能也很慢。构建一个 procedure or function (in the upcoming Neo4j 3.1) traversing the longest path(s), with the PathExpander
只返回当前节点具有最大权重的关系会容易得多。
正如@FrankPavageau 所说,在 Java 中编写解决方案可能更简单、更快。然而,通过利用现有的 APOC 过程 apoc.periodic.commit,您不必在 Java.
中实现任何内容
apoc.periodic.commit
将重复执行 Cypher 查询 直到它 return 的值为 0 或根本没有结果 。这是一个如何使用它来解决您的问题的示例。
首先,让我们创建您的示例数据:
CREATE (a:Foo {id: 'a'}), (b:Foo {id: 'b'}), (c:Foo {id: 'c'}), (d:Foo {id: 'd'}), (e:Foo {id: 'e'}), (f:Foo {id: 'f'}), (g:Foo {id: 'g'}),
(a)-[:NEXT {value: 3}]->(b),
(a)-[:NEXT {value: 4}]->(e),
(e)-[:NEXT {value: 3}]->(c),
(e)-[:NEXT {value: 1}]->(f),
(e)-[:NEXT {value: 2}]->(g),
(c)-[:NEXT {value: 3}]->(d),
(c)-[:NEXT {value: 2}]->(g);
此技术涉及您的 3 个查询:
创建带有 Temp
标签的临时节点的查询(在下面的步骤 2 中执行的重复执行之间保持状态,并保存最终结果)。 (在示例数据中,起始节点的 id
为 a
。)
MERGE (temp:Temp)
SET temp = {values: [], ids: ['a']};
调用 apoc.periodic.commit
的查询以重复执行传递的 Cypher 语句。每次执行 Cypher 语句时,它都会从最后找到的节点(id
在 temp.ids
尾端的节点)开始,并尝试找到关系最高的下一个节点value
值。如果最后一个节点是叶节点,那么 Cypher 语句 return 什么都没有(因为第二个 MATCH
将失败,中止该语句)——这将终止该过程;否则,Cypher 语句会将 max
值附加到 temp.values
并将相应的节点 id
附加到 temp.ids
,并且 return 1.
CALL apoc.periodic.commit("
MATCH (temp:Temp)
MATCH (:Foo {id: LAST(temp.ids)})-[n:NEXT]->(f:Foo)
WITH temp, REDUCE(s = {max: 0}, x IN COLLECT({v: n.value, id: f.id}) |
CASE WHEN x.v > s.max
THEN {max: x.v, id: x.id}
ELSE s
END
) AS curr
SET temp.values = temp.values + curr.max, temp.ids = temp.ids + curr.id
RETURN 1;
", NULL);
查询得到最终结果。 ids
集合将是沿 "maximum path" 的节点的 ID,而 values
集合将是沿同一路径的 NEXT
关系的 values
.
MATCH (temp:Temp)
RETURN temp;
结果如下:
╒══════════════════════════════════════╕
│temp │
╞══════════════════════════════════════╡
│{values: [4, 3, 3], ids: [a, e, c, d]}│
└──────────────────────────────────────┘
考虑一下我有以下带有边权重的图表:
我想知道我是否可以使用 CYPHER 执行从节点 a 开始的遍历,然后按照权重的递增顺序执行遍历。也就是上面应该return(a)-4->(e)-3->(c)-3->(d)
这可以使用密码吗?
您的描述略有错误(根据您的示例),因为您不想遍历具有增加权重的关系,您想要遍历关系每一步的 最大 权重。
您不能在 Cypher 中以通用方式执行此操作,因为结果是迭代构建的,并且您无法知道结果路径的最大长度。
在 Cypher 中,您必须
- 构建所有路径
- 按第一个关系的权重过滤它们
- 通过第二个关系的权重过滤剩余的(如果存在)
- 等等
Cypher 的声明性本质并不真正兼容:它会很麻烦,而且可能也很慢。构建一个 procedure or function (in the upcoming Neo4j 3.1) traversing the longest path(s), with the PathExpander
只返回当前节点具有最大权重的关系会容易得多。
正如@FrankPavageau 所说,在 Java 中编写解决方案可能更简单、更快。然而,通过利用现有的 APOC 过程 apoc.periodic.commit,您不必在 Java.
中实现任何内容apoc.periodic.commit
将重复执行 Cypher 查询 直到它 return 的值为 0 或根本没有结果 。这是一个如何使用它来解决您的问题的示例。
首先,让我们创建您的示例数据:
CREATE (a:Foo {id: 'a'}), (b:Foo {id: 'b'}), (c:Foo {id: 'c'}), (d:Foo {id: 'd'}), (e:Foo {id: 'e'}), (f:Foo {id: 'f'}), (g:Foo {id: 'g'}),
(a)-[:NEXT {value: 3}]->(b),
(a)-[:NEXT {value: 4}]->(e),
(e)-[:NEXT {value: 3}]->(c),
(e)-[:NEXT {value: 1}]->(f),
(e)-[:NEXT {value: 2}]->(g),
(c)-[:NEXT {value: 3}]->(d),
(c)-[:NEXT {value: 2}]->(g);
此技术涉及您的 3 个查询:
创建带有
Temp
标签的临时节点的查询(在下面的步骤 2 中执行的重复执行之间保持状态,并保存最终结果)。 (在示例数据中,起始节点的id
为a
。)MERGE (temp:Temp) SET temp = {values: [], ids: ['a']};
调用
apoc.periodic.commit
的查询以重复执行传递的 Cypher 语句。每次执行 Cypher 语句时,它都会从最后找到的节点(id
在temp.ids
尾端的节点)开始,并尝试找到关系最高的下一个节点value
值。如果最后一个节点是叶节点,那么 Cypher 语句 return 什么都没有(因为第二个MATCH
将失败,中止该语句)——这将终止该过程;否则,Cypher 语句会将max
值附加到temp.values
并将相应的节点id
附加到temp.ids
,并且 return 1.CALL apoc.periodic.commit(" MATCH (temp:Temp) MATCH (:Foo {id: LAST(temp.ids)})-[n:NEXT]->(f:Foo) WITH temp, REDUCE(s = {max: 0}, x IN COLLECT({v: n.value, id: f.id}) | CASE WHEN x.v > s.max THEN {max: x.v, id: x.id} ELSE s END ) AS curr SET temp.values = temp.values + curr.max, temp.ids = temp.ids + curr.id RETURN 1; ", NULL);
查询得到最终结果。
ids
集合将是沿 "maximum path" 的节点的 ID,而values
集合将是沿同一路径的NEXT
关系的values
.MATCH (temp:Temp) RETURN temp;
结果如下:
╒══════════════════════════════════════╕
│temp │
╞══════════════════════════════════════╡
│{values: [4, 3, 3], ids: [a, e, c, d]}│
└──────────────────────────────────────┘