Neo4j和Cypher:匹配与目标节点具有单一关系的节点

时间:2014-12-29 04:56:19

标签: neo4j cypher

我试图识别只有一种给定类型关系的节点。

想象一下Route和Stop节点的图表。路由可能有0个或多个停止,多个路由之间可以共享停止,停止必须始终至少有1个路由。我想匹配并删除在删除给定路由时将成为孤立的停止。

在任何人说什么之前,我知道在删除路线之后找到没有路线的站点会更容易,但这不是一个选项。我们也不担心在这里删除路线,只是停靠。

这是我的疑问:

MATCH (r1:Route { id: {route_id} })-[rel1:HAS_STOP]->(s:Stop)
MATCH (r2:Route)-[rel2:HAS_STOP]->(s)
WITH s, COUNT(rel2) as c
WHERE c = 1
MATCH s-[rel2]-()
DELETE s, rel2

这完美无缺......但有更好的方法吗?感觉它可能更有效但我不确定如何。

1 个答案:

答案 0 :(得分:2)

修改

此处的查询仅匹配将在不删除当前路由的情况下成为孤立的节点:

MATCH (route:Route {id:'99e08bdf-130f-3fca-8292-27d616fa025f'})
WITH route
OPTIONAL MATCH (route)-[r:HAS_STOP]->(s)
WHERE NOT EXISTS((route)--(s)<-[:HAS_STOP]-())
DELETE r,s

和执行计划:

neo4j-sh (?)$ PROFILE MATCH (route:Route {id:'99e08bdf-130f-3fca-8292-27d616fa025f'})
> WITH route
> OPTIONAL MATCH (route)-[r:HAS_STOP]->(s)
> WHERE NOT EXISTS((route)--(s)<-[:HAS_STOP]-())
> DELETE r,s;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 2
Relationships deleted: 2

EmptyResult
  |
  +UpdateGraph
    |
    +Eager
      |
      +OptionalMatch
        |
        +SchemaIndex(1)
        |
        +Filter
           |
           +SimplePatternMatcher
             |
             +SchemaIndex(1)

+----------------------+------+--------+--------------+----------------------------------------------------------------------------------------------------+
|             Operator | Rows | DbHits |  Identifiers |                                                                                              Other |
+----------------------+------+--------+--------------+----------------------------------------------------------------------------------------------------+
|          EmptyResult |    0 |      0 |              |                                                                                                    |
|          UpdateGraph |    2 |      4 |              |                                                                         DeleteEntity; DeleteEntity |
|                Eager |    2 |      0 |              |                                                                                                    |
|        OptionalMatch |    2 |      0 |              |                                                                                                    |
|       SchemaIndex(1) |    1 |      2 | route, route |                                                                        {  AUTOSTRING0}; :Route(id) |
|               Filter |    2 |      0 |              | NOT(nonEmpty(PathExpression((route)-[  UNNAMED140]-(s),(160)-[  UNNAMED145:HAS_STOP]->(s), true))) |
| SimplePatternMatcher |    2 |      0 |  route, s, r |                                                                                                    |
|       SchemaIndex(1) |    1 |      2 | route, route |                                                                        {  AUTOSTRING0}; :Route(id) |
+----------------------+------+--------+--------------+----------------------------------------------------------------------------------------------------+

Total database accesses: 8

** OLD ANSWER **

我让它在这里帮助别人:

在您的查询中,您不会删除路线,也不会删除不会孤立的停靠点的关系。你可以一气呵成。

这就是我查询相同用例的方法,我还比较了测试图上的两个执行计划,每个路由有大约160个停止点和2个停止位置,在删除路由后将成为孤立的,图形可在此处获取:http://graphgen.neoxygen.io/?graph=JPnvQWZcQW685m

我的查询:

MATCH (route:Route {id:'e70ea0d4-03e2-3ca4-afc0-dfdc1754868e'})
WITH route
MATCH (route)-[r:HAS_STOP]->(s)
WITH r, collect(s) as stops
DELETE r, route
WITH filter(x in stops WHERE NOT x--()) as orphans
UNWIND orphans as orphan
DELETE orphan

这是我的个人资料查询:

       neo4j-sh (?)$ PROFILE MATCH (route:Route {id:'1c565ac4-b72b-37c3-be7f-a38f2a7f66a8'})
> WITH route
> MATCH (route)-[r:HAS_STOP]->(s)
> WITH route, r, collect(s) as stops
> DELETE r, route
> WITH filter(x in stops WHERE NOT x--()) as orphans
> UNWIND orphans as orphan
> DELETE orphan;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 2
Relationships deleted: 157

EmptyResult
  |
  +UpdateGraph(0)
    |
    +UNWIND
      |
      +ColumnFilter(0)
        |
        +Eager
          |
          +Extract
            |
            +UpdateGraph(1)
              |
              +ColumnFilter(1)
                |
                +EagerAggregation
                  |
                  +SimplePatternMatcher
                    |
                    +SchemaIndex

+----------------------+------+--------+--------------+------------------------------+
|             Operator | Rows | DbHits |  Identifiers |                        Other |
+----------------------+------+--------+--------------+------------------------------+
|          EmptyResult |    0 |      0 |              |                              |
|       UpdateGraph(0) |    1 |      1 |              |                 DeleteEntity |
|               UNWIND |    1 |      0 |              |                              |
|      ColumnFilter(0) |  157 |      0 |              |         keep columns orphans |
|                Eager |  157 |      0 |              |                              |
|              Extract |  157 |      0 |              |                      orphans |
|       UpdateGraph(1) |  157 |    158 |              |   DeleteEntity; DeleteEntity |
|      ColumnFilter(1) |  157 |      0 |              | keep columns route, r, stops |
|     EagerAggregation |  157 |      0 |              |                     route, r |
| SimplePatternMatcher |  157 |      0 |  route, s, r |                              |
|          SchemaIndex |    1 |      2 | route, route |  {  AUTOSTRING0}; :Route(id) |
+----------------------+------+--------+--------------+------------------------------+

Total database accesses: 161

使用您的查询:

我稍微修改了您的查询以使用模式索引

这是您查询的执行计划,数据库访问的差异非常大

PROFILE MATCH (r1:Route { id: '1c565ac4-b72b-37c3-be7f-a38f2a7f66a8' })
> WITH r1
> MATCH (r1)-[rel1:HAS_STOP]->(s:Stop)
> MATCH (r2:Route)-[rel2:HAS_STOP]->(s)
> WITH s, COUNT(rel2) as c
> WHERE c = 1
> MATCH s-[rel2]-()
> DELETE s, rel2;
+-------------------+
| No data returned. |
+-------------------+
Nodes deleted: 1
Relationships deleted: 1

EmptyResult
  |
  +UpdateGraph
    |
    +Eager
      |
      +SimplePatternMatcher(0)
        |
        +Filter(0)
          |
          +ColumnFilter
            |
            +EagerAggregation
              |
              +Filter(1)
                |
                +SimplePatternMatcher(1)
                  |
                  +Filter(2)
                    |
                    +SimplePatternMatcher(2)
                      |
                      +SchemaIndex

+-------------------------+------+--------+-----------------------+-----------------------------+
|                Operator | Rows | DbHits |           Identifiers |                       Other |
+-------------------------+------+--------+-----------------------+-----------------------------+
|             EmptyResult |    0 |      0 |                       |                             |
|             UpdateGraph |    1 |      2 |                       |  DeleteEntity; DeleteEntity |
|                   Eager |    1 |      0 |                       |                             |
| SimplePatternMatcher(0) |    1 |      0 |   UNNAMED200, s, rel2 |                             |
|               Filter(0) |    1 |      0 |                       |           c == {  AUTOINT1} |
|            ColumnFilter |  157 |      0 |                       |           keep columns s, c |
|        EagerAggregation |  157 |      0 |                       |                           s |
|               Filter(1) | 4797 |   4797 |                       |       hasLabel(r2:Route(4)) |
| SimplePatternMatcher(1) | 4797 |   4797 |           r2, s, rel2 |                             |
|               Filter(2) |  157 |    157 |                       |         hasLabel(s:Stop(3)) |
| SimplePatternMatcher(2) |  157 |    157 |           r1, s, rel1 |                             |
|             SchemaIndex |    1 |      2 |                r1, r1 | {  AUTOSTRING0}; :Route(id) |
+-------------------------+------+--------+-----------------------+-----------------------------+

Total database accesses: 9912