2015-11-13 81 views
4

問題的另一陣列的內部的陣列刪除元素

假設我有一個文件如下:如何從嵌套使用的MongoDB

doc = { 
"_id" : ObjectId("56464c726879571b1dcbac79"), 
"food" : { 
    "fruit" : [ 
     "apple", 
     "orange" 
    ] 
}, 
"items" : [ 
    { 
     "item_id" : 750, 
     "locations" : [ 
      { 
       "store#" : 13, 
       "num_employees" : 138 
      }, 
      { 
       "store#" : 49, 
       "num_employees" : 343 
      } 
     ] 
    }, 
    { 
     "item_id" : 650, 
     "locations" : [ 
      { 
       "store#" : 12, 
       "num_employees" : 22 
      }, 
      { 
       "store#" : 15, 
       "num_employees" : 52 
      } 
     ] 
    } 
] 
} 


我想刪除元素

{'#store#' : 12, 'num_employees' : 22} 

只有下列條件:

  • food.fruit包含的值appleorange
  • item_id有ID 650



我嘗試的解決方案

我試過如下:

 db.test.update({"food.fruit" : {"$in" : ["apple", "orange"]}, "items.item_id":650},{$pull:{'items.$.locations':{'store#':12,'num_employees':22}}}) 


更新不起作用。有趣的是,如果查詢中的$ in操作符部分被刪除,它就可以工作。我使用MongoDB的v3.0.6和諮詢的MongoDB手冊使用$(更新)

https://docs.mongodb.org/manual/reference/operator/update/positional/

該文檔包含感興趣的話:

Nested Arrays 
    The positional $ operator cannot be used for queries which traverse more than one array, such as queries that traverse arrays nested within other arrays, because the replacement for the $ placeholder is a single value 

我的查詢當然,遍歷多個數組。事實上,如果我從查詢中刪除'food.fruit' : {$in : ['apple']},它就會起作用。但是,這並不能解決我的問題,因爲當然,我需要那個查詢。我正在尋找一個解決方案,較好的是:

  • 不需要架構更改
  • 執行一個查詢/更新語句
+0

當您嘗試使用3.0.5時,您嘗試的更新正常。值得注意的是,你不需要在這裏使用'$ in'作爲''food.fruit':'apple''也可以做同樣的事情,但是更新對我來說無論如何都能正常工作。 – JohnnyHK

+0

@JohnnyHK,它使用$ in操作符?我需要編輯我的示例,因爲我尋找的不僅僅是「蘋果」。例如:'{$ in:['apple','orange']}'。使用你的建議,我可以做'food.fruit':'apple','food.fruit':'orange''這應該相當於使用'$ in'。 – matt

+0

哎呀。其實,這是行不通的。我試圖看看'food.fruit'是否有'apple'或'orange'。只需要至少有一個。 – matt

回答

0

馬特,

我用您的樣本數據和下面的查詢工作:

db.pTest.update(
    {"food.fruit" : "apple","items.item_id":650}, 
    {$pull:{'items.$.locations':{'store#':12,'num_employees':22}}} 
) 

無需爲$in(除非你輸入多於一個值)或$elemMatch。對於兩級深度陣列,您也可以使用{$pull: {"someArray.$.someNestedArray": {"key": "value to delete"}}}

你從文檔中引用的內容。

嵌套數組 的位置$操作者可以不被用於橫穿多個陣列的查詢,諸如遍歷嵌套在其它陣列內的數組查詢,因爲更換爲$佔位符是一個單一的值。

轉換爲,意味着您不能使用兩次$ Positional運算符。

樣本數據:在

{ 
    "_id" : ObjectId("56464c726879571b1dcbac79"), 
    "food" : { 
     "fruit" : [ 
      "apple", 
      "orange" 
     ] 
    }, 
    "items" : [ 
     { 
      "item_id" : 650, 
      "locations" : [ 
       { 
        "store#" : 12, 
        "num_employees" : 22 
       }, 
       { 
        "store#" : 15, 
        "num_employees" : 52 
       } 
      ] 
     } 
    ] 
} 

結果:

{ 
    "_id" : ObjectId("56464c726879571b1dcbac79"), 
    "food" : { 
     "fruit" : [ 
      "apple", 
      "orange" 
     ] 
    }, 
    "items" : [ 
     { 
      "item_id" : 650, 
      "locations" : [ 
       { 
        "store#" : 15, 
        "num_employees" : 52 
       } 
      ] 
     } 
    ] 
} 
+0

感謝您的回答。我已經更新了我現在應該具有可重現問題的問題。道歉。我試圖模仿我正在使用的實際文檔的結構,因爲我無法在公共論壇上發佈其數據。 – matt

1

如果您需要在"food.fruit",因此其他多個可能的文檔(只能如此匹配多個可能的值這是有道理的),那麼你總是可以用$where中的JavScript邏輯代替$in

db.test.update(
    { 
     "items.item_id": 650, 
     "$where": function() { 
      return this.food.fruit.some(function(el) { 
       return ["apple","orange"].indexOf(el) != -1; 
      }); 
     } 
    }, 
    { "$pull": { "items.$.locations": { "store#": 12 } } }, 
    { "multi": true } 
) 

基本上適用相同的測試,雖然性能不如"food.fruit"值不能在索引中進行測試,但希望的"items.item_id另一場「是一個足以匹配至少不使這個現實的問題。

在另一方面,這種測試針對的MongoDB服務器版本3.1.9(開發系列),下面的工作沒有任何問題:

db.test.update(
    { "food.fruit": { "$in": ["orange","apple"] }, "items.item_id": 650 }, 
    { "$pull": { "items.$.locations": { "store#": 12 } } }, 
    { "multi": true } 
) 

我也建議的是,如果你打算包括_id在您的查詢,那麼你只反正匹配單個文件,因此你只需要提供你希望$pull陣列上的匹配:

db.test.update(
    { "_id": 123, "items.item_id": 650 }, 
    { "$pull": { "items.$.locations": { "store#": 12 } } } 
) 

這是相當簡單,並且不提供衝突,除非你確實需要以確保所需的"food.fruits"值實際上存在才能應用更新。在這種情況下,請按照前面的例子。

+0

謝謝七。我剛剛更新了我的問題。我現在才意識到我遇到的問題,並沒有提供我提供的信息的可複製性。我現在會讀你的答案。 – matt

+0

@matt由於您使用的是相同的cookie切割器響應,因此您似乎很清楚您沒有閱讀過任何人實際回覆過的內容。你沒有改變你的問題中的任何細節,這對答覆沒有任何影響,你也不應該這樣做。問題「在問題發生時」提供了答案。如果你有不同的問題,那麼[問另一個問題](http://stackoverflow.com/questions/ask)。這回答了問題。 –

+0

經過啓發回答後,我讀了他/她的回答,進行了更多調查,並意識到我需要編輯我的問題,以包含更多結構來重現我的問題。所以在堆棧溢出,我應該開始一個新的問題?或者直接編輯我目前的問題。看來編輯我目前的問題是合理的。我現在要讀你的。 – matt