首页 > 解决方案 > neo4j 按距离聚合函数

问题描述

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

(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 的直接邻居和第二层邻居的平均值,即

+-------------------+
| 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 进行操作。

同样,是否可以得到累积值?IE,

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

标签: neo4jcypher

解决方案


下面的查询解决了第一个问题。请注意,它还解决了路径长度不等的情况。我添加了 (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

返回

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

推荐阅读