图分组
大型图通常难以理解或可视化。
表格结果可以进行聚合以生成概览,例如在包含总和、计数等的图表中。
将节点按属性值分组为虚拟节点,有助于在图可视化中实现同样的效果。
在此过程中,这些组之间的关系也会被聚合,因此您只会看到汇总信息。
此功能灵感来源于 Martin Junghanns 在 Gradoop 图处理系统的 分组演示 (Grouping Demo) 中的工作。
基本上,您可以使用任何 (entity)<-->(entity) 图进行分组,对图投影 (graph projections) 的支持正在规划中。
这是一个使用 :play movies 数据集的示例。
MATCH (n)
SET n.century = toInteger(coalesce(n.born,n.released)/100) * 100;
CALL apoc.nodes.group(['Person','Movie'],['century']);
|
有时,UI 处理分组的返回值(节点列表和关系列表)时可能会出现问题,此时运行以下代码可能会有所帮助:
|
使用
CALL apoc.nodes.group(labels,properties, [grouping], [config])
唯一必需的参数是 label-list(也可以是 ['*'])和用于分组的 属性名称列表(适用于关系和节点)。
您还可以选择提供按字段的分组运算符以及一系列配置选项。
分组运算符
对于分组运算符,您需要按以下格式为每个字段提供一个 MAP 操作:{fieldName: [operators]}
节点一个 map,关系一个 map:[{nodeOperators},{relOperators}]
可选运算符
-
count_* -
count -
sum -
min/max -
avg -
collect
默认值为:[{`*`:"count"},{`*`:"count"}],即仅对节点和关系进行计数。
配置
配置中还有更多选项
| 选项 | 默认 | description(描述) |
|---|---|---|
|
|
在结果图中显示自引用关系 |
|
|
在结果图中显示孤立节点 |
|
|
限制节点的最大数量 |
|
|
限制关系的最大数量 |
|
|
限制每个节点的关系数量 |
|
|
按属性值进行最小/最大过滤,例如 |
|
|
包含的关系类型。默认为包含所有关系类型。可以是类型列表或单个类型。 |
|
|
排除的关系类型。默认为不排除任何关系类型。可以是类型列表或单个类型。 |
filter 配置选项是一个 {Label/TYPE.operator_property.min/max: number} 格式的 MAP,其中 Label/TYPE. 前缀是可选的。
因此,例如,您可以仅过滤分组中最小年龄为 21 岁的人:Person.min_age.min: 21,或者过滤拥有最多 10 个 KNOWS 共同关系的人:KNOWS.count_*.max:10。
示例
CREATE
(alice:Person {name:'Alice', gender:'female', age:32, kids:1}),
(bob:Person {name:'Bob', gender:'male', age:42, kids:3}),
(eve:Person {name:'Eve', gender:'female', age:28, kids:2}),
(graphs:Forum {name:'Graphs', members:23}),
(dbs:Forum {name:'Databases', members:42}),
(alice)-[:KNOWS {since:2017}]->(bob),
(eve)-[:KNOWS {since:2018}]->(bob),
(alice)-[:MEMBER_OF]->(graphs),
(alice)-[:MEMBER_OF]->(dbs),
(bob)-[:MEMBER_OF]->(dbs),
(eve)-[:MEMBER_OF]->(graphs)
CALL apoc.nodes.group(['*'],['gender'],
[{`*`:'count', age:'min'}, {`*`:'count'} ])
| 节点 | relationships | 节点 | 关系 (relationship) |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
请注意,此查询在 Neo4j Browser 的“图形”模式下无法运行,仅在“表格”模式(或 cypher-shell)下有效。这是因为 Forum 没有 gender 属性,在 node 结果中会出现 "gender": null 属性,这不被支持并会返回 TypeError。相反,下面的查询在“图形”模式下也可以正常工作。
CALL apoc.nodes.group(
['Person'],['gender'],
[{`*`:'count', kids:'sum', age:['min', 'max', 'avg'], gender:'collect'},
{`*`:'count', since:['min', 'max']}]);
大型示例
WITH ["US","DE","UK","FR","CA","BR","SE"] AS tld
UNWIND range(1,1000) AS id
CREATE (u:User {id:id, age : id % 100, female: rand() < 0.5, name: "Name "+id, country:tld[toInteger(rand()*size(tld))]})
WITH collect(u) AS users
UNWIND users AS u
WITH u, users[toInteger(rand()*size(users))] AS u2
WHERE u <> u2
MERGE (u)-[:KNOWS]-(u2);
CALL apoc.nodes.group(['*'], ['country'])
YIELD node, relationship return *
CALL apoc.nodes.group(['*'], ['country'], null,
{selfRels:false, orphans:false,
filter:{`User.count_*.min`:130,`KNOWS.count_*.max`:200}})
YIELD node, relationship return *
要在 Neo4j Browser 中可视化此结果,使用自定义图形样式表 (GRASS) 非常有用,它可以用一些聚合数据来渲染分组后的属性。
node {
diameter: 50px;
color: #A5ABB6;
border-color: #9AA1AC;
border-width: 2px;
text-color-internal: #FFFFFF;
font-size: 10px;
}
relationship {
color: #A5ABB6;
shaft-width: 3px;
font-size: 8px;
padding: 3px;
text-color-external: #000000;
text-color-internal: #FFFFFF;
caption: '{count_*}';
}
node.Country {
color: #68BDF6;
diameter: 80px;
border-color: #5CA8DB;
text-color-internal: #FFFFFF;
caption: '{country} ({count_*})';
}