2014-12-29 196 views
1

我試圖確定只有一個給定類型關係的節點。Neo4j和Cypher:匹配與目標節點有單一關係的節點

想象一下Route和Stop節點的圖形。一條路線可能有0個或更多的停靠點,一個停靠點可能會在多個路線之間共享,一個停車點必須至少有一條路線。如果給定的路線被刪除,我想要匹配並刪除將成爲孤兒的站點。

在任何人說什麼之前,我知道在路由被刪除後找到沒有路由的站點比較容易,但這不是一個選項。我們也不擔心在這裏刪除路線,只是站點。

這裏是我的查詢:

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 

這工作完全...但有沒有更好的辦法?感覺它可能更高效,但我不知道如何。

回答

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 **

I讓它在這裏幫助其他人:

在您的查詢中,您不會刪除路線,也不會刪除與不會成爲孤兒的站點之間的關係。你可以一氣呵成。

這就是我對查詢相同用例的情況,我還比較了兩個執行計劃的測試圖,每個路由有大約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 

有了您的查詢:

我稍微修改您的查詢利用模式索引

,並且這與您的查詢的執行計劃,以dB爲單位的不同訪問是相當高的

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 
+0

真的很有趣,謝謝!我在帖子中提到,我只需要刪除站點而不是路線。這被用作'before_destroy'回調的一部分,所以Route需要被保留到最後,因爲可能有其他類似的查詢會對它執行。 – subvertallchris

+0

好吧,沒有趕上它:) –

+0

我編輯了一個匹配你想要的查詢 –

相關問題