You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何编写Cypher查询按关系类型动态分组关联节点?

问题描述

数据模型

(PersonA)-[:KNOWS]->(PersonB)
(PersonA)-[:KNOWS]->(PersonC)
(PersonA)-[:IS_FRIENDS_WITH]->(PersonD)
(PersonA)-[:LIKES]->(PersonE)

需求

编写Cypher查询返回PersonA,以及按关系类型分组的关联人员列表,输出格式如下:

{
     "id": "PersonA",
     "knows": [
         {"id": "PersonB"},
         {"id": "PersonC"}
     ],
     "is_friends_with": [
         {"id": "PersonD"}
     ],
     "likes": [
         {"id": "PersonE"}
     ]
}

核心要求:不能硬编码关系类型,支持任意关系类型。

遇到的问题

尝试使用apoc.map.groupMulti,但该函数仅支持按节点属性分组,无法按关系类型分组,寻求解决办法。

解决方案

可以结合Cypher原生函数和APOC工具函数实现动态分组,以下是两种可行写法:

写法一:COLLECT + apoc.map.fromPairs

MATCH (a:Person {id: 'PersonA'})-[r]->(b)
WITH a, LOWER(TYPE(r)) AS relType, COLLECT({id: b.id}) AS people
WITH a, COLLECT([relType, people]) AS relGroups
RETURN apoc.map.fromPairs(COLLECT(['id', a.id]) + relGroups) AS result

代码说明

  • 匹配目标节点PersonA及其所有向外的关系、关联节点
  • 将关系类型转为小写(和示例输出格式对齐),收集同一关系类型下的所有关联节点信息
  • 把每个关系类型与对应人员列表打包成键值对数组,再加入PersonA的ID键值对
  • 用apoc.map.fromPairs将键值对数组转换为最终的JSON格式对象

如果不需要关系类型小写,直接去掉LOWER()函数即可。

写法二:apoc.agg.groupBy(更简洁)

MATCH (a:Person {id: 'PersonA'})-[r]->(b)
WITH a, apoc.agg.groupBy(TYPE(r), {id: b.id}) AS relGroups
RETURN apoc.map.merge({id: a.id}, relGroups) AS result

代码说明

  • apoc.agg.groupBy可直接按关系类型(TYPE(r))分组,自动收集对应关系下的关联节点信息
  • 最后用apoc.map.merge将PersonA的ID和分组结果合并成符合要求的对象

内容的提问来源于stack exchange,提问作者oculardexterity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 04:50:23