Cypher:查找节点之间的任何路径

时间:2017-07-03 03:58:06

标签: neo4j cypher

我有一个看起来像这样的neo4j图:

Graph overview

节点

  1. 蓝色节点:帐户
  2. 红色节点:PhoneNumber
  3. 绿色节点:电子邮件
  4. 图表设计:

    • (:PhoneNumber) - [:PART_OF] - >(:帐户)
    • (:电子邮件) - [:PART_OF] - >(:帐户)

    我想解决的问题是

      

    查找Account1和Account2之间存在的任何路径。

    这是我迄今为止尝试过的,但没有成功:

    1. MATCH p = shortestPath((a1:Account {accId:'1234'}) - [] - (a2:Account {accId:'5678'}))RETURN p;
    2. MATCH p = shortestPath((a1:Account {accId:'1234'}) - [:PART_OF] - (a2:Account {accId:'5678'}))RETURN p;
    3. MATCH p = shortestPath((a1:Account {accId:'1234'}) - [*] - (a2:Account {accId:'5678'}))RETURN p;
    4. MATCH p =(a1:Account {accId:'1234'})< - [:PART_OF * 1..100] - (n) - [:PART_OF] - >(a2:Account {accId:' 5678'})RETURN p;
    5. 与上述相同的查询,没有最短路径函数调用。
    6. 通过查看图表,我可以看到这两个节点之间存在路径,但我的查询都没有产生任何结果。我确信这是一个非常简单的查询,但对Cypher来说是新手,我很难找到正确的解决方案。任何帮助表示赞赏。

      感谢。

1 个答案:

答案 0 :(得分:4)

所有这些查询都是正确的,但需要进行一些调整才能完成工作。但是,从长远来看,为了获得更好的系统来轻松搜索帐户之间的连接,您可能希望重构图表。

现在的解决方案:让您的查询有效

图表中任意两个(n:Account)节点之间的路径看起来像这样:

(a1:Account)<-[:PART_OF]-(:Email)-[:PART_OF]->(ai:Account)<-[:PART_OF]-(:PhoneNumber)-[:PART_OF]->(a2:Account)

由于图表中只有一种类型的关系,因此两个节点将通过不确定数量的模式连接,如下所示:

<-[:PART_OF]-(:Email)-[:PART_OF]->

<-[:PART_OF]-(:PhoneNumber)-[:PART_OF]->

因此,您的两个节点将通过不确定数量的中间(:Account)(:Email)(:PhoneNumber)节点连接,这些节点全部通过交替方向的-[:PART_OF]-关系连接。不幸的是,据我所知(我希望在这里得到纠正),使用直线密码,你无法在当前图形中搜索这样的重复模式。因此,您只需使用无向搜索,即可找到通过(a1:Account)关系连接的节点(a2:Account)-[:PART_OF]-。所以,乍一看你的查询看起来像这样:

MATCH p=shortestPath((a1:Account { accId: {a1_id} })-[:PART_OF*]-(a2:Account { accId: {a2_id} }))
RETURN *

(注意这里我使用了cypher parameters而不是你在原帖中输入的整数)

这与你的查询#3非常相似,但是,就像你说的那样 - 它不起作用。我猜测会发生什么,它不返回结果,或返回内存不足异常?问题是,由于你的图形中有圆形路径,并且该查询将匹配任何长度的路径,匹配算法将逐渐绕圈,直到它耗尽内存。因此,您希望设置一个限制,就像在查询#4中一样,但没有指示(这就是查询不起作用的原因)。

所以,让我们设定一个限制。您对100个关系的限制有点偏大,特别是在循环图(即带圆圈的图)中,并且可能在2 ^ 100个路径的区域内匹配。

作为一个(非常随意的)经验法则,任何具有潜在无向和未标记路径长度超过5或6的查询都可能会引发问题,除非您对图形设计非常小心。在您的示例中,看起来这两个节点通过路径长度为8连接。我们还知道,对于任何两个节点,给定的最小路径长度将是两个(即两个-[:PART_OF]-关系,一个进入和标记为:Email:PhoneNumber的节点中的一个,并且任何两个帐户(如果链接)将通过偶数关系链接。

因此,理想情况下,我们将关系长度设置为2到10.但是,cypher的shortestPath()函数仅支持最小长度为0或1的路径,因此我将其设置为1和以下示例中的10(尽管我们知道实际上,最短路径的长度至少为2)。

MATCH p=shortestPath((a1:Account { accId: {a1_id} })-[:PART_OF*1..10]-(a2:Account { accId: {a2_id} }))
RETURN *

希望这适用于您的用例,但请记住,在大型图表上运行可能仍会占用大量内存。

长期解决方案:重构图表和/或使用APOC

根据您的使用案例,更好或更长期的解决方案是重构您的图表,以便更加具体地了解关系,以便在您想要查找仅通过电子邮件或电话号码链接的帐户时加快查询时间 - 即{{1 }和-[:ACCOUNT_HAS_EMAIL]-。然后,您可能还想使用APOC的shortest path algorithmspath finder functions,它们很可能会返回比使用cypher更快的结果,并允许您更加具体地了解关系类型,因为您的图表会扩展以吸收更多内容数据