2012-09-27 60 views
0

我想更新一個子數組的子文檔,但我不能指望數組中的元素位置始終相同,所以如何更新它。使用MongoDB,當元素位置未知時,如何更新子數組的子文檔?

例如,這裏是我的文檔,我只是想推另一個標籤的對象(鍵/ VAL)到tags陣列的real_pagenum:1的PDF與_idObjectId("50634e26dc7c22c64d00000a")

{ 
    "_id" : ObjectId("503b83dfad79cc8d26000004"), 
    "pdfs" : [ 
     { 
      "_id" : ObjectId("50634e26dc7c22c64d00000a"), 
      "pages" : [ 
       { 
        "real_pagenum" : 1, 
        "_id" : ObjectId("50634e74dc7c22c64d00002b"), 
        "tags" : [ 
         { 
          "key" : "Item", 
          "val" : "foo" 
         }, 
         { 
          "key" : "Item", 
          "val" : "bar" 
         } 

        ] 

       }, 
       { 
        "real_pagenum" : 2, 
        "_id" : ObjectId("50634e74dc7c22c64d00002b") 
       } 
      ], 
      "title" : "PDF3", 
      "version" : 3 
     } 
    ], 
} 

重申,我們的目標是首先由_id,然後在右側頁面通過real_pagenum瞄準正確的PDF和推成PDF格式的網頁的tags陣列。

我曾嘗試:

db.projects.update({'pdfs.pdf_id':ObjectId("50634e25dc7c22c64d000007")}, 
    {$push:{'pages.$.tags':{'key':'foo','val':'bar'}}},false,false); 

但這並不得到我所需要的水平。我讀過我可以使用combination of the positional operator with actual element position,但我再次無法保證或不知道元素的位置。

回答

1

這是目前不可能的。您只能使用位置運算符來處理文檔樹中的最高級別數組。如果您知道確切的元素位置,則只能訪問任何較深的陣列。

這是目前一個懸而未決的問題:https://jira.mongodb.org/browse/SERVER-831

0

這是MongoDB中當前提交的bug,該位置操作不能用於嵌套的數組:

https://jira.mongodb.org/browse/SERVER-831

的位置運營商也不能暫時在一個查詢中多次使用。

來處理這個,你的情況可能會改變你的架構的最佳方式。通常,將文檔中的數組放入任意大小不是一個好主意,因爲BSON文檔的最大大小爲16mb。

特別是因爲在這種情況下,它看起來像你的文件基本上是PDF文件的數組。你有沒有考慮過爲pdf創建一個單獨的集合?

0

其他的答案是正確的,只要做文檔的原子更新。

我非常同意,這看起來像不到最佳模式 - 每一個PDF文件可能會更有意義,那麼你只需要的,你可以與位置操作原子更新每個文檔內的頁面的陣列。

如果不能修改架構,你仍然可以讓你想要的更新,它可能無法雖然線程安全的。您可以將整個文檔讀入應用程序,修改代碼中的相應字段,然後保存該項目。如果你想確保多個線程不會相互踩踏,你必須在每個文檔中保留一個版本,並在每次「更新」時增加它,這將取決於版本在同一時間沒有被更改。它更復雜,它仍然需要在當前模式中增加一個字段,但至少它可以讓你做你需要做的事情。

相關問題