使用Cypher以关系权重的递增顺序遍历Neo4j图

时间:2016-11-28 12:23:16

标签: neo4j cypher neo4j-traversal-api

考虑我有以下带边权的图:

enter image description here

我想知道我是否可以使用CYPHER在节点a和后续边缘处执行遍历,并增加其权重的顺序。上面应该返回(a)-4->(e)-3->(c)-3->(d)

这可以使用cypher吗?

2 个答案:

答案 0 :(得分:3)

正如@FrankPavageau所述,用Java编写解决方案可能不那么麻烦和快捷。然而,通过利用现有的APOC过程apoc.periodic.commit,您不必在Java中实现任何东西。

apoc.periodic.commit将重复执行Cypher查询,直到它返回值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个查询:

  1. 创建具有Temp标签的临时节点的查询(在下面的步骤2中执行的重复执行之间保持状态,并保存最终结果)。 (在示例数据中,起始节点的ida。)

    MERGE (temp:Temp)
    SET temp = {values: [], ids: ['a']};
    
  2. 调用apoc.periodic.commit以执行传递的Cypher语句的重复执行的查询。每次执行Cypher语句时,它都从最后找到的节点(id位于temp.ids尾端的节点)开始,并尝试查找其关系最高的下一个节点value值。MATCH如果最后一个节点是叶节点,则Cypher语句不返回任何内容(因为第二个max将失败,中止语句) - 这将终止该过程;否则,Cypher语句会将temp.values值附加到id,将相应的节点temp.ids附加到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); ,然后返回1.

    ids
  3. 获取最终结果的查询。 values集合将是“最大路径”上节点的ID,values集合将是同一路径上NEXT个关系的MATCH (temp:Temp) RETURN temp;

    ╒══════════════════════════════════════╕
    │temp                                  │
    ╞══════════════════════════════════════╡
    │{values: [4, 3, 3], ids: [a, e, c, d]}│
    └──────────────────────────────────────┘
    
  4. 结果如下:

    <?php 
    include('phpqrcode/qrlib.php');
    ?>
    
    <html>
    <body>
      <?php 
      $studentno = 123456;
      $image = $studentno.'.png';
    
      QRcode::png($studentno, $image);
      ?>
      <img src="<?php echo $image; ?>" />
    </body>
    </html>
    

答案 1 :(得分:1)

您的描述略有错误(基于您的示例),因为您不希望遍历与增加权重的关系,您想要使用遍历关系每一步的最大重量

您不能在Cypher中以通用方式执行此操作,因为结果是迭代构建的,并且您无法知道结果路径的最大长度。

在Cypher,你必须

  1. 构建所有路径
  2. 按第一关系的重量过滤它们
  3. 按第二关系的权重(如果存在)过滤剩余的那些
  4. Cypher的声明性质并不真正兼容:它会很麻烦,也可能很慢。构建procedure或函数(在即将发布的Neo4j 3.1中)traversing最长的路径会更容易,PathExpander仅返回最大权重的关系当前节点。