Cypher查询如何按子节点类型稀有度排序优先返回稀有类型结果
优化后Cypher查询
MATCH (Parent)-[R]-(Child) WHERE ID(Parent)=$parentId // 统计当前Parent下每个子节点标签的总数量,用于判定稀有度 WITH Parent, R, Child, count(*) OVER (PARTITION BY labels(Child)[0]) as tagTotalCount // 保留原有子节点度数计算逻辑 CALL { WITH Child RETURN apoc.node.degree(Child) as ChildDegree } WITH Parent, Child, R, ChildDegree, tagTotalCount // 优先按标签总数量升序排列,数量越少稀有度越高,同标签下保留原排序规则 RETURN Parent, Child, type(R), ChildDegree ORDER BY tagTotalCount ASC, R LIMIT 35
实现逻辑说明
- 新增窗口函数
count(*) OVER (PARTITION BY labels(Child)[0])统计当前Parent关联的所有子节点中,每个标签对应的总数量,存储为tagTotalCount字段- 若子节点存在多标签场景,可调整
labels(Child)的取值逻辑,比如按指定标签优先级取值、或把全部标签拼接为分组key
- 若子节点存在多标签场景,可调整
- 排序逻辑调整为优先按
tagTotalCount升序排列,标签总数量越小(稀有度越高)的子节点越靠前,保证稀有标签的结果优先被返回 - 同标签下的排序保留原有的
R排序规则,也可根据业务需要调整为按ChildDegree等其他字段排序 - 最终返回结果会优先取完所有稀有标签的记录后,再取占比高的标签的记录,刚好满足示例中2条C、3条B、30条A的返回需求
低版本Neo4j兼容方案(不支持窗口函数时使用)
MATCH (Parent)-[R]-(Child) WHERE ID(Parent)=$parentId // 预计算每个标签的总数量与对应记录集合 WITH Parent, labels(Child)[0] as childTag, collect({child:Child, rel:R}) as tagRecords, count(*) as tagTotalCount // 按标签数量升序排序,保证稀有标签在前 ORDER BY tagTotalCount ASC // 展开所有记录,此时稀有标签的记录天然排在前面 UNWIND tagRecords as record WITH Parent, record.child as Child, record.rel as R, tagTotalCount CALL { WITH Child RETURN apoc.node.degree(Child) as ChildDegree } RETURN Parent, Child, type(R), ChildDegree ORDER BY tagTotalCount ASC, R LIMIT 35
内容的提问来源于stack exchange,提问作者ablaszkiewicz1
相关产品推荐
相关产品推荐

