查询图中所有顶点出入边时无法显示无对应边的顶点计数问题
解决Cypher查询显示所有顶点入/出边计数(含0值)的问题
需求:检索图中所有顶点的入边和出边,要求即使顶点仅有单种边或无任何边,也需展示对应边的计数为0,而非仅显示同时拥有入边和出边的顶点。
示例场景:创建了名为SocialNetwork的图,顶点类型为用户(Person)和页面/群组(Page/Group),边类型包括消息、点赞、好友关系。其中用户Charlie仅有出边,无入边。
原查询的问题
原查询使用MATCH强制匹配边,导致仅返回存在对应边的顶点:
仅查询入边的原结果(缺失Charlie)
-- incoming edges SELECT * FROM cypher('SocialNetwork', $$ MATCH in_edge = (a)<-[ie]-(c) RETURN a.name, label(a), count(in_edge) $$) AS (id agtype, label agtype, in_edges agtype);
输出:
id | label | in_edges --------------------+----------+---------- "Photography Club" | "Group" | 2 "Hiking Group" | "Group" | 2 "Chicago Bulls" | "Page" | 2 "David" | "Person" | 1 "Book Club" | "Group" | 2 "Emma" | "Person" | 2 "Dance Class" | "Group" | 2 "Frank" | "Person" | 1 "Bob" | "Person" | 1 "Gaming Group" | "Group" | 2 "Grace" | "Person" | 2 (11 rows)
仅查询出边的原结果(包含Charlie)
-- Outgoing edges SELECT * FROM cypher('SocialNetwork', $$ MATCH out_edge = (a)-[oe]->(b) RETURN a.name, label(a), count(out_edge) $$) AS (id agtype, label agtype, out_edges agtype);
输出:
id | label | out_edges -----------+----------+----------- "Charlie" | "Person" | 6 "David" | "Person" | 2 "Emma" | "Person" | 2 "Alice" | "Person" | 3 "Frank" | "Person" | 3 "Bob" | "Person" | 1 "Grace" | "Person" | 2 (7 rows)
同时查询入边和出边的原结果(缺失Charlie、Alice等)
-- People that have both SELECT * FROM cypher('SocialNetwork', $$ MATCH out_edge = (a)-[oe]->(b), in_edge = (a)<-[ie]-(c) RETURN a.name, label(a), count(out_edge) $$) AS (id agtype, label agtype, in_and_out_edges agtype);
输出:
id | label | in_and_out_edges ---------+----------+------------------ "David" | "Person" | 2 "Emma" | "Person" | 4 "Frank" | "Person" | 3 "Bob" | "Person" | 1 "Grace" | "Person" | 4 (5 rows)
正确解决方案:使用OPTIONAL MATCH
OPTIONAL MATCH会保留所有初始匹配的顶点(即图中所有节点),若顶点无对应边,匹配结果为null,count(null)会返回0,正好满足需求。
1. 查询所有顶点的入边计数(含入边为0的顶点)
-- 所有顶点的入边计数(含入边为0的顶点) SELECT * FROM cypher('SocialNetwork', $$ MATCH (a) OPTIONAL MATCH in_edge = (a)<-[ie]-(c) RETURN a.name, label(a), count(ie) AS in_edges $$) AS (id agtype, label agtype, in_edges agtype);
输出会包含Charlie的入边计数0:
id | label | in_edges -----------+----------+---------- "Charlie" | "Person" | 0 -- 其他顶点结果省略
2. 查询所有顶点的出边计数(含出边为0的顶点)
-- 所有顶点的出边计数(含出边为0的顶点) SELECT * FROM cypher('SocialNetwork', $$ MATCH (a) OPTIONAL MATCH out_edge = (a)-[oe]->(b) RETURN a.name, label(a), count(oe) AS out_edges $$) AS (id agtype, label agtype, out_edges agtype);
3. 同时查询所有顶点的入边和出边计数
-- 所有顶点的入边和出边计数(含任意一种边为0的顶点) SELECT * FROM cypher('SocialNetwork', $$ MATCH (a) OPTIONAL MATCH in_edge = (a)<-[ie]-(c) OPTIONAL MATCH out_edge = (a)-[oe]->(b) RETURN a.name, label(a), count(ie) AS in_edges, count(oe) AS out_edges $$) AS (id agtype, label agtype, in_edges agtype, out_edges agtype);
内容的提问来源于stack exchange,提问作者Matheus Farias
相关产品推荐
相关产品推荐

