Neo4j:及时匹配多重关系

时间:2016-04-18 16:45:52

标签: graph neo4j cypher

考虑使用两种类型的边相互连接的节点:直接和相交。查询需要发现满足以下所有规则的2个节点之间的所有可能路径:

  • 0..N直接边
  • 0..1相交边
  • 相交边可以在直边之间

这些路径在nodeA和nodeZ之间被认为是有效的:

  • (nodeA)-[:direct]->(nodeB)-[:direct]->(nodeC)->[:direct]->(nodeZ)
  • (nodeA)-[:intersect]->(nodeB)-[:direct]->(nodeC)->[:direct]->(nodeZ)
  • (nodeA)-[:direct]->(nodeB)-[:intersect]->(nodeC)->[:direct]->(nodeZ)
  • (nodeA)-[:direct]->(nodeB)->[:direct]->(nodeC)-[:intersect]->(nodeZ)

基本上相交边可以发生在路径中的任何地方,但只能发生一次。 我在不存在的neo4j版本中的理想密码查询是这样的:

MATCH (from)-[:direct*0..N|:intersect*0..1]->(to)

但是neo4j并不支持边类型的多个约束:(。

更新23.04.16

有6609个节点(总共550k),5184个直接类型的边缘(总共440k)和34119个类型相交(总共37289个)。预期会有一些循环引用(neo4j避免了,不是吗?)

看起来很有希望但却未能以秒的方式完成的查询:

MATCH p = (from {from: 1})-[:direct|intersect*0..]->(to {to: 99}) WHERE 123 < from.departureTS < 123 + 86400 //next day AND REDUCE(s = 0, x IN RELATIONSHIPS(p) | CASE TYPE(x) WHEN 'intersect' THEN s + 1 ELSE s END) <= 1 return p;

2 个答案:

答案 0 :(得分:2)

这是符合规定要求的查询:

MATCH p = (from)-[:direct|intersect*0..]->(to) 
WHERE REDUCE(s = 0, x IN RELATIONSHIPS(p) |
  CASE WHEN TYPE(x) = 'intersect' THEN s + 1 ELSE s END) <= 1 
return p;

它返回所有具有0个或更多direct个关系以及0或1个intersect关系的路径。

答案 1 :(得分:1)

这将做你想要的:

// Cybersam's correction:
MATCH p = ((from)-[:direct*0..]->(middle)-[:intersect*0..1]->(middle2)-[:direct*0..]->(to)‌​) return DISTINCT p;
return p

这是我使用的测试场景:

create (a:nodeA {name: "A"})
create (b:nodeB {name: "B"})
create (c:nodeC {name: "C"})
create (z:nodeZ {name: "Z"})

merge (a)-[:direct      {name: "D11"}]->(b)-[:direct     {name: "D21"}]->(c)-[:direct     {name: "D31"}]->(z)
merge (a)-[:intersect   {name: "I12"}]->(b)-[:direct     {name: "D22"}]->(c)-[:direct     {name: "D32"}]->(z)
merge (a)-[:direct      {name: "D13"}]->(b)-[:intersect  {name: "I23"}]->(c)-[:direct     {name: "D33"}]->(z)
merge (a)-[:direct      {name: "D14"}]->(b)-[:direct     {name: "D24"}]->(c)-[:intersect  {name: "I34"}]->(z)
merge (a)-[:intersect   {name: "I15"}]->(z)

// Cybersam's correction:
MATCH p = ((from)-[:direct*0..]->(middle)-[:intersect*0..1]->(middle2)-[:direct*0..]->(to)‌​) return DISTINCT p;
return p

我错误地认为浏览器上的图形反映了&#34; p&#34;中返回的数据。 - 它没有,你必须看看&#34;行&#34;获取所有细节的报告的一部分。

此查询还将返回符合要求的单个节点。