neo4j多个匹配聚合 - 单次通过图表?

时间:2017-11-29 13:37:47

标签: graph neo4j cypher

我有一个图表 enter image description here

在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', 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)

neo4j percentage of attribute for social network 允许轻松计算社交网络的欺诈百分比:

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

而是有一些东西会返回percentage_total, percentage_sms, percentage_phone

1 个答案:

答案 0 :(得分:2)

如果您希望将结果保持在一起,则需要使用WITH对查询进行链接,并为该人传递f变量。不幸的是,您还必须继续传递所有percentage_*子句中的所有WITH变量,因此很难维护:

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项目提议nested subqueries,但这需要一些时间才能完成Neo4j。

相关问题