【问题标题】:neo4j aggregate function by distanceneo4j 按距离聚合函数
【发布时间】:2021-11-11 04:25:04
【问题描述】:

我想通过与根的距离获得一些汇总统计信息。例如,

(A)-[值:20]->(B)-[值:40]->(C)

(A)-[值:0]->(D)-[值:20]->(E)

CREATE (:firm {name:'A'}), (:firm {name:'B'}), (:firm {name:'C'}), (:firm {name:'D'}), (:firm {name:'E'});
MATCH (a:firm {name:'A'}), (b:firm {name:'B'}), (c:firm {name:'C'}), (d:firm {name:'D'}), (e:firm {name:'E'})
CREATE (a)-[:REL {value: 20}]->(b)->[:REL {value: 40}]->(c),
(a)-[:REL {value: 0}]->(d)->[:REL {value: 20}]->(e);

我想得到A的直接邻居和第2层邻居的平均值,即,

+-------------------+
| distance |  avg   |
+-------------------+
| 1        |   10   |
| 2        |   30   |
+-------------------+

我该怎么做?我已经尝试了以下

MATCH p=(n:NODE {name:'A'})-[r:REL*1..2]->(n:NODE)
RETURN length(p), sum(r:value);

但是我不确定如何对变长路径r进行操作。

同理,是否可以得到累计值?即,

+-------------------+
| name     |  cum   |
+-------------------+
| B        |   20   |
| C        |   60   |
| D        |   0    |
| E        |   20   |
+-------------------+

【问题讨论】:

    标签: neo4j cypher


    【解决方案1】:

    下面的查询解决了第一个问题。请注意,它还解决了路径长度不等的情况。我添加了 (E)-[REL {value:99}]->(F)

    MATCH path=(:firm {name:'A'})-[:REL*]->(leaf:firm)
    WHERE NOT (leaf)-[:REL]->(:firm)
    WITH COLLECT(path) AS paths, max(length(path)) AS longest
    UNWIND RANGE(1,longest) AS depth
    WITH depth,
         REDUCE(sum=0, path IN [p IN paths WHERE length(p) >= depth] |
                sum 
                + relationships(path)[depth-1].value
         ) AS sumAtDepth,
         SIZE([p IN paths WHERE length(p) >= depth]) AS countAtDepth
    
    RETURN depth, sumAtDepth, countAtDepth, sumAtDepth/countAtDepth AS avgAtDepth
    

    返回

    ╒═══════╤════════════╤══════════════╤════════════╕
    │"depth"│"sumAtDepth"│"countAtDepth"│"avgAtDepth"│
    ╞═══════╪════════════╪══════════════╪════════════╡
    │1      │20          │2             │10          │
    ├───────┼────────────┼──────────────┼────────────┤
    │2      │60          │2             │30          │
    ├───────┼────────────┼──────────────┼────────────┤
    │3      │99          │1             │99          │
    └───────┴────────────┴──────────────┴────────────┘
    

    第二个问题可以这样回答:

    MATCH (root:firm {name:'A'})
    MATCH (descendant:firm) WHERE EXISTS((root)-[:REL*]->(descendant))
    WITH root,descendant
    WITH descendant,
         REDUCE(sum=0,rel IN relationships([(descendant)<-[:REL*]-(root)][0][0]) |
                sum + rel.value
         ) AS cumulative
    RETURN descendant.name,cumulative  ORDER BY descendant.name
    

    返回

    ╒═════════════════╤════════════╕
    │"descendant.name"│"cumulative"│
    ╞═════════════════╪════════════╡
    │"B"              │20          │
    ├─────────────────┼────────────┤
    │"C"              │60          │
    ├─────────────────┼────────────┤
    │"D"              │0           │
    ├─────────────────┼────────────┤
    │"E"              │20          │
    ├─────────────────┼────────────┤
    │"F"              │119         │
    └─────────────────┴────────────┘
    

    【讨论】:

    • 谢谢!一个相关的查询:如果每个公司都有一个“类型”值,是否可以逐层计算类型的数量?我了解如何通过 "MATCH path=(:firm {name:'A'})-[:REL*]->(leaf:firm) return leaf.type, count(*);" 来计算所有内容
    • @cccfran 是的,这是可能的。请打开另一个问题。
    • 谢谢。我在这里发布了另一个问题:stackoverflow.com/questions/70415734/…
    • @cccfran 知道了;)
    【解决方案2】:

    我可以建议您使用 reduce 函数尝试一下,您可以将其重新安装到您的代码中

    // Match something name or distance..
    MATCH 
    // If you have a condition put in here
    // WHERE A<>B AND n.name = m.name
    // WITH filterItems, collect(m) AS myItems
    // Reduce will help sum/aggregate entire you are looking for
    RETURN reduce( sum=0, x IN myItems | sum+x.cost )
    LIMIT 10;
    

    【讨论】:

      猜你喜欢
      • 2015-07-03
      • 2022-01-21
      • 2016-01-10
      • 1970-01-01
      • 2017-03-31
      • 1970-01-01
      • 2021-01-24
      • 2016-02-16
      • 1970-01-01
      相关资源
      最近更新 更多