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

标签 neo4j cypher

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

Graph overview

节点:

  • 蓝色节点:账号
  • 红色节点:电话号码
  • 绿色节点:邮箱

  • 图形设计:
  • (:PhoneNumber) -[:PART_OF]->(:Account)
  • (:Email) -[:PART_OF]->(:Account)

  • 我试图解决的问题是

    Find any path that exists between Account1 and Account2.



    这是我迄今为止尝试过但没有成功的方法:
  • MATCH p=shortestPath((a1:Account {accId:'1234'})-[]-(a2:Account {accId:'5678'})) RETURN p;
  • MATCH p=shortestPath((a1:Account {accId:'1234'})-[:PART_OF]-(a2:Account {accId:'5678'})) RETURN p;
  • MATCH p=shortestPath((a1:Account {accId:'1234'})-[*]-(a2:Account {accId:'5678'})) RETURN p;
  • MATCH p=(a1:Account {accId:'1234'})<-[:PART_OF*1..100]-(n)-[:PART_OF]->(a2:Account {accId:'5678'}) RETURN p;
  • 与上述相同的查询,没有最短路径函数调用。

  • 通过查看图表,我可以看到这两个节点之间有一条路径,但我的查询都没有产生任何结果。我确信这是一个非常简单的查询,但作为 Cypher 的新手,我很难找出正确的解决方案。任何帮助表示赞赏。

    谢谢。

    最佳答案

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

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

    任意两个之间的路径(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 的路径长度连接。我们还知道,对于任何两个节点,给定的最小路径长度将为 2(即,两个 -[: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

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

    关于neo4j - Cypher:查找节点之间的任何路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44877585/

    相关文章:

    neo4j - 是否可以在大型密集图上使用 graphdb

    jruby - bundler 无法识别平台?找不到 gem

    neo4j - 优化从庞大数据集中计算两个节点之间 Jackard 相似度的查询

    neo4j - 按路径顺序返回节点的密码查询

    sql-server - 从 SQL Server 迁移到 neo4j ,是否有类似 SSMS 的东西将数据导入到 neo4j 中

    neo4j - 了解 Neo4j Cypher Profile 关键字和执行计划

    java - 如何提高 Neo4j 2.0 cypher/ExecutionResult 在重负载下的性能?

    java - 从 java 执行密码查询 (Neo4j)

    c# - Neo4J - 将所有关系从一个节点复制到另一个节点(C# Wrapper)

    Neo4j Cypher 查找子节点没有属性值的节点