前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用Cypher获取指定结构的树

使用Cypher获取指定结构的树

作者头像
马超的博客
发布2022-09-02 10:28:35
8040
发布2022-09-02 10:28:35
举报
文章被收录于专栏:马超的博客马超的博客

@TOC[1] Here's the table of contents:

•一、来自社区的问题链接•二、编写查询实现数据封装 •2.1 创建样例数据 •2.2 Cypher实现

使用Cypher获取指定结构的树

一、来自社区的问题链接

Neo4j 图数据库中文社区:如何获取指定结构的树?[2]

但是相同层级的node我希望去除重复项后作为一个数组,比如下图:

但是简单的这样处理后会丢失父节点以及关系,我希望每个节点转换为一个map对象,这个对象包含了原本的节点,以及父节点的id,关系的名称方便在客户端直接序列化 可是我试了好多办法,只能对单列这样处理,多列就变成笛卡尔积了!

二、编写查询实现数据封装

2.1 创建样例数据

2.2 Cypher实现

分层封装数据获取指定结构的树,返回结果中每一层每个节点包含该节点关联的关系ID、节点ID;如果需要在返回结果中包含节点、关系属性和类型信息,可以在对应Cypher查询位置处进行封装一并返回。

代码语言:javascript
复制
// 匹配需要处理的路径
MATCH p=(c:Class {name:'电影'})-[r1:实例]->(m:Movie)<-[r2:ACTED_IN]-(:Person) 
    // 收集两层关系
    WITH COLLECT(DISTINCT r1) AS hc_r1,COLLECT(DISTINCT r2) AS hc_r2
    // 解析第一层NODE,第二层NODE,第三层NODE
    // NODE对象结构:node-当前层节点,f_node表示父级节点,rel表示当前节点的关系
    WITH REDUCE(l=[],r IN hc_r1 | l+apoc.map.setPairs({},[["node",ID(STARTNODE(r))],["rel",ID(r)]])) AS hc_n1,
        REDUCE(l=[],r IN hc_r1 | l+apoc.map.setPairs({},[["f_node",ID(STARTNODE(r))],["node",ID(ENDNODE(r))],["rel",ID(r)]])) AS hc_n2,
        REDUCE(l=[],r IN hc_r2 | l+apoc.map.setPairs({},[["f_node",ID(ENDNODE(r))],["node",ID(STARTNODE(r))],["rel",ID(r)]])) AS hc_n3
    // 通过上一次处理后,每一层节点、关联关系以及父级节点都准备好了,下一步需要将`node`排重,然后将`f_node`和`rel`收集在一个数组
    // 当前节点的父级节点和关联关系可能有多个,所以排重后需要增加两个map字段`f_nodes`和`rels`
    WITH hc_n1,hc_n2,hc_n3
    WITH apoc.map.groupByMulti(hc_n1,'node') AS hc_n1_gp,EXTRACT(map IN hc_n1 | map.node) AS hc_n_l1, 
        apoc.map.groupByMulti(hc_n2,'node') AS hc_n2_gp,EXTRACT(map IN hc_n2 | map.node) AS hc_n_l2, 
        apoc.map.groupByMulti(hc_n3,'node') AS hc_n3_gp,EXTRACT(map IN hc_n3 | map.node) AS hc_n_l3
    // 封装最终返回的每一层数据格式[{cur_node:node,f_nodes:[2,123],rels:[213,23]}]
    WITH REDUCE(l=[],nd IN hc_n_l1 | l+apoc.map.setPairs({},[["cur_node",nd],["f_nodes",apoc.coll.toSet(FILTER(e IN EXTRACT(mp IN apoc.map.get(hc_n1_gp,TOSTRING(nd),NULL,FALSE) | mp.f_node) WHERE e IS NOT NULL))],["rels",apoc.coll.toSet(FILTER(e IN EXTRACT(mp IN apoc.map.get(hc_n1_gp,TOSTRING(nd),NULL,FALSE) | mp.rel) WHERE e IS NOT NULL))]])) AS hc1,
        REDUCE(l=[],nd IN hc_n_l2 | l+apoc.map.setPairs({},[["cur_node",nd],["f_nodes",apoc.coll.toSet(FILTER(e IN EXTRACT(mp IN apoc.map.get(hc_n2_gp,TOSTRING(nd),NULL,FALSE) | mp.f_node) WHERE e IS NOT NULL))],["rels",apoc.coll.toSet(FILTER(e IN EXTRACT(mp IN apoc.map.get(hc_n2_gp,TOSTRING(nd),NULL,FALSE) | mp.rel) WHERE e IS NOT NULL))]])) AS hc2,
        REDUCE(l=[],nd IN hc_n_l3 | l+apoc.map.setPairs({},[["cur_node",nd],["f_nodes",apoc.coll.toSet(FILTER(e IN EXTRACT(mp IN apoc.map.get(hc_n3_gp,TOSTRING(nd),NULL,FALSE) | mp.f_node) WHERE e IS NOT NULL))],["rels",apoc.coll.toSet(FILTER(e IN EXTRACT(mp IN apoc.map.get(hc_n3_gp,TOSTRING(nd),NULL,FALSE) | mp.rel) WHERE e IS NOT NULL))]])) AS hc3
// 使用apoc.coll.toSet排重列表
RETURN apoc.coll.toSet(hc1) AS hc1,
        apoc.coll.toSet(hc2) AS hc2,
        apoc.coll.toSet(hc3) AS hc3

References

[1] TOC: 使用Cypher获取指定结构的树 [2] Neo4j 图数据库中文社区:如何获取指定结构的树?: http://neo4j.com.cn/topic/619ab67c03dea95514def1b1

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-11-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 马超的博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Cypher获取指定结构的树
  • 一、来自社区的问题链接
  • 二、编写查询实现数据封装
    • 2.1 创建样例数据
      • 2.2 Cypher实现
        • References
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档