Graph neo4j多重匹配聚合-单传递图?
我有一张像这样的图 在neo4j中Graph neo4j多重匹配聚合-单传递图?,graph,neo4j,cypher,Graph,Neo4j,Cypher,我有一张像这样的图 在neo4j中 CREATE (Alice:Person {id:'a', fraud:1}) CREATE (Bob:Person {id:'b', fraud:0}) CREATE (Charlie:Person {id:'c', fraud:0}) CREATE (David:Person {id:'d', fraud:0}) CREATE (Esther:Person {id:'e', fraud:0}) CREATE (Fanny:Person {id:'f',
CREATE (Alice:Person {id:'a', fraud:1})
CREATE (Bob:Person {id:'b', fraud:0})
CREATE (Charlie:Person {id:'c', fraud:0})
CREATE (David:Person {id:'d', fraud:0})
CREATE (Esther:Person {id:'e', fraud:0})
CREATE (Fanny:Person {id:'f', fraud:0})
CREATE (Gabby:Person {id:'g', fraud:0})
CREATE (Fraudster:Person {id:'h', fraud:1})
CREATE
(Alice)-[:CALL]->(Bob),
(Bob)-[:SMS]->(Charlie),
(Charlie)-[:SMS]->(Bob),
(Fanny)-[:SMS]->(Charlie),
(Esther)-[:SMS]->(Fanny),
(Esther)-[:CALL]->(David),
(David)-[:CALL]->(Alice),
(David)-[:SMS]->(Esther),
(Alice)-[:CALL]->(Esther),
(Alice)-[:CALL]->(Fanny),
(Fanny)-[:CALL]->(Fraudster)
允许轻松计算社交网络的欺诈百分比:
MATCH (:Person)-[:CALL|:SMS]->(f:Person)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs
UNWIND fs AS f
WITH divisor, f
WHERE f.fraud = 1
RETURN f, COUNT(*)/divisor AS percentage
如何修改此选项以对不同类型的关系使用多个匹配项,但仍然只需要对图形进行一次遍历?也就是说,有比简单地调用以下3个语句更有效的方法:
MATCH (:Person)-[:CALL]->(f:Person)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs
UNWIND fs AS f
WITH divisor, f
WHERE f.fraud = 1
RETURN f, COUNT(*)/divisor AS percentage
MATCH (:Person)-[:SMS]->(f:Person)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs
UNWIND fs AS f
WITH divisor, f
WHERE f.fraud = 1
RETURN f, COUNT(*)/divisor AS percentage
MATCH (:Person)-[:CALL|:SMS]->(f:Person)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs
UNWIND fs AS f
WITH divisor, f
WHERE f.fraud = 1
RETURN f, COUNT(*)/divisor AS percentage
但是,如果您想将结果保存在一起,您需要使用
与链接查询,并为此人传递f
变量,而不是返回percentage\u total、percentage\u sms、percentage\u phone
?。不幸的是,您还必须使用
子句在所有中传递所有百分比*
变量,因此很难维护:
MATCH (f:Person)
OPTIONAL MATCH (:Person)-[:CALL|:SMS]->(f)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs
UNWIND fs AS f
WITH divisor, f
WHERE f.fraud = 1
WITH f, COUNT(*)/divisor AS percentage_all
OPTIONAL MATCH (:Person)-[:CALL]->(f)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs, percentage_all
UNWIND fs AS f
WITH divisor, f, percentage_all
WHERE f.fraud = 1
WITH f, percentage_all, COUNT(*)/divisor AS percentage_phone
OPTIONAL MATCH (:Person)-[:SMS]->(f)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs, percentage_all, percentage_phone
UNWIND fs AS f
WITH divisor, f, percentage_all, percentage_phone
WHERE f.fraud = 1
RETURN f, percentage_all, percentage_phone, COUNT(*)/divisor AS percentage_sms
openCypher项目已经提出,但这将需要一些时间才能实现Neo4j。如果您希望将结果保存在一起,则需要使用与
链接查询,并为人员传递f
变量。不幸的是,您还必须使用
子句在所有中传递所有百分比*
变量,因此很难维护:
MATCH (f:Person)
OPTIONAL MATCH (:Person)-[:CALL|:SMS]->(f)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs
UNWIND fs AS f
WITH divisor, f
WHERE f.fraud = 1
WITH f, COUNT(*)/divisor AS percentage_all
OPTIONAL MATCH (:Person)-[:CALL]->(f)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs, percentage_all
UNWIND fs AS f
WITH divisor, f, percentage_all
WHERE f.fraud = 1
WITH f, percentage_all, COUNT(*)/divisor AS percentage_phone
OPTIONAL MATCH (:Person)-[:SMS]->(f)
WITH TOFLOAT(COUNT(*))/100 AS divisor, COLLECT(f) AS fs, percentage_all, percentage_phone
UNWIND fs AS f
WITH divisor, f, percentage_all, percentage_phone
WHERE f.fraud = 1
RETURN f, percentage_all, percentage_phone, COUNT(*)/divisor AS percentage_sms
提议的openCypher项目,但这需要一些时间才能实现Neo4j。UNION
不是一个选项?但这只会连接结果,而不会为一个顶点提供3个不同的列?UNION
不是一个选项?但这只会连接结果,而不会为一个顶点提供3个不同的列?尽管最后一个应该是第一个查询-和其他所有可选匹配,即当前返回一个空集。好的一点-我更新了查询,为所有三个查询添加了可选项。另外一个改进是简单地通过平均值进行聚合(假设欺诈为0或1,以更有效地计算百分比avg(f.fraud)
-但我不确定如何将其集成到cypher中。虽然最后一个应该是第一个查询,其余的都是可选的匹配项,即当前返回一个空集。很好的一点是,我更新了查询,为所有三个查询都添加了可选项。还有一个改进是简单地通过平均值聚合(假设欺诈为0或1,以更有效地计算百分比avg(f.fraud)
——但我不确定如何将其集成到cypher中。