具有正则表达式和循环关系的Neo4j查询节点冻结浏览器

时间:2016-02-24 20:20:56

标签: regex performance neo4j cypher circular-reference

我有一个图表,其中节点可以是'资源'或者'外部依赖'。

资源(a.k.a。微服务)可能具有以下关系:

  1. 资源 - DEPENDS_ON - > externalDependency(maxDepth为1,单向)
  2. 资源 - CONNECTS_TO - 资源(任何深度,任何方向)
  3. 我目前正在使用以下查询搜索所有资源及其关系(进出):

    Match (Resource)-[:CONNECTIONS*0..]-(ResourceDependency)-[:DEPENDS_ON*0..]-(ExternalDependency) 
    Where Resource.name =~ '.*service_name.*' 
    Return Resource, ResourceDependency, ExternalDependency
    

    由于资源可以相互依赖,它们可能形成循环关系。当发生这种情况时,属于该圆圈的其中一个节点与" name"匹配。标准,查询永远不会完成,neo4j浏览器最终冻结。

    如果我尝试将CONNECTIONS深度/ maxHops降低到8(* 0..8),它可以完美地工作。不幸的是,我已经拥有了比这更大的关系,所以这不是一个可行的解决方案(他们只是不会形成任何循环rel。)。

    更新:

    将maxHops设置为任何高于8的值会使Neo4j浏览器崩溃。

    因为'资源'节点可以彼此具有N个深度关系(并最终形成循环引用),查询需要遍历所有图形,从而获得所有资源节点及其(一个深度)外部依赖关系的进出关系。

    问题:

    我怎样才能实现这一目标"其中"没有关于循环关系的表现问题的条款?

2 个答案:

答案 0 :(得分:0)

下面的查询可能更适合您。如果没有,您可能想尝试在一个或多个可变长度路径上设置合理的上限。你可能比以前尝试的更高限制。

MATCH (resource:Resource)-[:CONNECTIONS*0..]->(resourceDependency)
WHERE resource.name =~ '.*service_name.*' AND (resourceDependency)-[:DEPENDS_ON]->()
WITH resourceDependency, COLLECT(resource) AS resources
MATCH (resourceDependency)-[:DEPENDS_ON*]->(externalDependency)
RETURN resourceDependency, resources, COLLECT(externalDependency) AS externalDependencies;

查询:

  1. 假设您的资源节点具有Resource标签,并使用它。如果您未指定标签,则neo4j必须扫描数据库中的每个节点,以查看它是否具有:CONNECTIONS:DEPENDS_ON关系。如果指定标签,neo4j只能扫描Resource个节点。
  2. 指定所有关系的方向,这可以快速消除查询当前所执行的所有关系遍历的一半。
  3. 使用[:CONNECTIONS*0..]获取所有依赖项,包括resource本身。
  4. 包含此测试:(resourceDependency)-[:DEPENDS_ON]->()仅获取具有传出resourceDependency关系的:DEPENDS_ON个节点。
  5. 为每个此类resourceDependency聚合所有依赖它的resources。作为副作用,这确保了在此之后我们最终只有不同的resourceDependency节点。我们以这种方式聚合是因为resourceDependency可能依赖于大量资源,因此,在以下步骤中,我们希望确保我们尝试查找每个resourceDependency的外部依赖项一旦
  6. 查找每个externalDependency所依赖的所有resourceDependency个节点。请注意,我们使用[:DEPENDS_ON*],相当于[:DEPENDS_ON*1..],因为我认为resourceDependency不能也是externalDependency
  7. 返回每个resourceDependency,依赖于它的resource个节点的集合,以及它所依赖的externalDependency个节点的集合。

答案 1 :(得分:0)

Cypher的可变长度模式匹配正在寻找与该模式匹配的所有可能路径,当您寻找不同的连接节点时,这并不是最有效的方法。

我们可以使用path expander procs in APOC Procedures来匹配不同的可达资源依赖项节点,然后从那里匹配到可能的外部依赖项。

MATCH (Resource) // you really should be using labels, WHERE CONTAINS, and indexes
WHERE Resource.name =~ '.*service_name.*' 
CALL apoc.path.subgraphNodes(Resource, {relationshipFilter:'CONNECTIONS'}) YIELD node as ResourceDependency
MATCH (ResourceDependency)-[:DEPENDS_ON*0..1]->(ExternalDependency)
RETURN Resource, ResourceDependency, ExternalDependency

请注意,您将看到重复的数据,因为可以交换Resource和ResourceDependency的节点。如果您想减少这一点,可以在CALL之后添加以下内容:

...
WITH Resource, ResourceDependency
WHERE id(Resource) <= id(ResourceDependency)
...