请大佬解答这种关系如何写cql可以一次性返回想要的结果集
发布于 2 年前 作者 neokomiya 391 次浏览 来自 问答

image.png,如图, 该结构node之间有父子关系,与绿色node之间有属性关系,想在java中返回 list: 如 [{node:{},childnodeList:[{node:{},childnodeList:[],rel2:{}}],rel2:{}}],尝试多次都是平铺,不是想要结果。

1 回复

下面是一个图数据查询加数据解析操作的样例,所有操作全部使用查询语句实现,希望可以为你提供一些思路:)

使用Cypher+Apoc封装指定格式的JSON数据

  • 样例数据的结构

image.png

  • Cypher实现
// 分层封装数据【获取指定结构的树】,返回结果中每一层每个节点包含该节点关联的关系ID、节点ID;如果需要在返回结果中包含节点、关系属性和类型信息,可以在对应Cypher查询位置处进行封装一并返回。
// 匹配需要处理的路径
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
  • 返回结果 image.png

参考链接:使用Cypher获取指定结构的树

回到顶部