在neo4j中查找公共源的起始节点之间的匹配

时间:2016-11-06 21:07:41

标签: neo4j cypher

作为某些分析的一部分,我试图找到具有超过80%的单跳路径共同起源的目标。

数据类型:所有节点都是系统,唯一相关的关系是ConnectsTo

所以,我可以编写像

这样的查询
match (n:system)-[r:ConnectsTo]->(m:system) return n,m

获取系统n的来源m

我希望找到所有具有80%或更多常见源系统的系统。

请告知如何为所有系统完成此操作。我尝试使用收集,但恐怕无法编写正确的迭代。

1 个答案:

答案 0 :(得分:1)

让我们首先创建一个简单的示例数据集:

CREATE
  (s1:System {name:"s1"}), 
  (s2:System {name:"s2"}), 
  (s3:System {name:"s3"}), 
  (s4:System {name:"s4"}), 
  (s5:System {name:"s5"}), 
  (s1)-[:ConnectsTo]->(s3),
  (s1)-[:ConnectsTo]->(s4),
  (s2)-[:ConnectsTo]->(s3),
  (s2)-[:ConnectsTo]->(s4),
  (s2)-[:ConnectsTo]->(s5)

结果如下图所示。

enter image description here

我们从至少有一个共同源的节点对(m1m2)开始。我们计算:

  • 每个节点(sources1Countsources2Count
  • 的来源数量
  • 常见来源(commonSources
  • 的数量

然后我们将公共源的数量与节点的源数量进行比较。根据您认为的“80%常见”,这可能会使用一些微调。需要toFloat函数来避免类型不匹配。

查询:

MATCH (m1)<-[:ConnectsTo]-()-[:ConnectsTo]->(m2)
MATCH
  (n1)-[:ConnectsTo]->(m1),
  (n2)-[:ConnectsTo]->(m2)
WITH m1, m2, COUNT(DISTINCT n1) AS sources1Count, COUNT(DISTINCT n2) AS sources2Count
MATCH (m1)<-[:ConnectsTo]-(n)-[:ConnectsTo]->(m2)
WITH m1, m2, sources1Count, sources2Count, COUNT(n) AS commonSources
WHERE
  // we only need each m1-m2 pair once
  ID(m1) < ID(m2) AND
  // similarity
  commonSources / 0.8 >= sources1Count AND
  commonSources / 0.8 >= sources2Count
RETURN m1, m2
ORDER BY m1.name, m2.name

这给出了以下结果。

╒══════════╤══════════╕
│m1        │m2        │
╞══════════╪══════════╡
│{name: s3}│{name: s4}│
└──────────┴──────────┘

PS。为了检查相似性,你可以使用类似的东西:

sources1Count <= toInt(commonSources / 0.8) >= sources2Count

这避免了0.8的重复,但看起来不太好。

更新:评论中来自InverseFalcon的想法:使用SIZE代替MATCHCOUNT

MATCH (m1)<-[:ConnectsTo]-()-[:ConnectsTo]->(m2)
WITH m1, m2, SIZE(()-[:ConnectsTo]->(m1)) as sources1Count, SIZE(()-[:ConnectsTo]->(m2)) as sources2Count
MATCH (m1)<-[:ConnectsTo]-(n)-[:ConnectsTo]->(m2)
WITH m1, m2, sources1Count, sources2Count, COUNT(n) AS commonSources
WHERE
    // we only need each m1-m2 pair once
    ID(m1) < ID(m2) AND
    // similarity
    commonSources / 0.8 >= sources1Count AND
    commonSources / 0.8 >= sources2Count
RETURN m1, m2
ORDER BY m1.name, m2.name