2014-10-29 72 views
2

我有一個包含此類結構的mongodb集合。如何更新數組中的元素作爲mongoDb中的數組中的對象,並使用貓鼬

modules: [ { systems:[ { systemId: 13, count: 2 }, { systemId: 20, count: 7 }, { systemId: 8, count: 1 } ] }, { systems:[ { systemId: 13, count: 2 }, { systemId: 20, count: 7 } ] } ]

什麼,我試圖做的是updatemodule包含systemsystemId = 13$set是整個系統{d: null}

,使它看起來像這樣算賬:

modules: [ { systems:[ { d: null }, { systemId: 20, count: 7 }, { systemId: 8, count: 1 } ] }, { systems:[ { d: null }, { systemId: 20, count: 7 } ] } ]

回答

4

因爲你有嵌套數組,所以直到添加來自SERVER-831的功能請求才能作爲單個查詢進行。一旦嵌套$elemMatch運營商被允許,那麼你的更新將如下所示。 注:本目前不工作,語法甚至尚未定義 - 它是僅用於說明目的

db.foo.update(
    {modules: {$elemMatch: { systems: {$elemMatch: {systemId : 13}}}}}, 
    { $set : {"modules.$0.systems.$1" : {d : null}}} 
); 

這一發現一塊查詢的工作當前,但更新件作品將不允許即使您從理論上的$0$1恢復到當前的$,也會出現多個位置運算符。

即使那麼你會碰到$ elemMatch上的第一個元素匹配限制(它不匹配多個/所有元素,只是它找到的第一個元素),因此你可能不得不多次運行這個來更新所有文檔,至少要到SERVER-1243完成。

爲了說明如何做到這一點與單個陣列的工作是非常簡單的,讓我們將您的樣品文檔拖放模塊領域:

db.bar.insert([{ 
      systems:[ 
       { systemId: 13, count: 2 }, 
       { systemId: 20, count: 7 }, 
       { systemId: 8, count: 1 } 
      ] 
     }, 
     { 
      systems:[ 
       { systemId: 13, count: 2 }, 
       { systemId: 20, count: 7 } 
      ] 
     } 
    ]); 

這基本上是創建兩個文件(它把每個元素的數組中要插入的文檔)。所以,我們有2個文檔現在:

> db.bar.find() 
{ "_id" : ObjectId("5450e0708e1b8924251e1330"), "systems" : [ { "systemId" : 13, "count" : 2 }, { "systemId" : 20, "count" : 7 }, { "systemId" : 8, "count" : 1 } ] } 
{ "_id" : ObjectId("5450e0708e1b8924251e1331"), "systems" : [ { "systemId" : 13, "count" : 2 }, { "systemId" : 20, "count" : 7 } ] } 

要更新這些文檔所概述(只要有只爲systemId : 13一場比賽,你就可以做到以下幾點:

>db.bar.update(
    { systems: {$elemMatch: {systemId : 13}}}, 
    { $set : {"systems.$" : {d : null}}}, 
    {multi : true} 
); 
WriteResult({ "nMatched" : 2, "nUpserted" : 0, "nModified" : 2 }) 

讓我們來看看在我們的文檔中再次提到:

> db.bar.find() 
{ "_id" : ObjectId("5450e1198e1b8924251e1332"), "systems" : [ { "d" : null }, { "systemId" : 20, "count" : 7 }, { "systemId" : 8, "count" : 1 } ] } 
{ "_id" : ObjectId("5450e1198e1b8924251e1333"), "systems" : [ { "d" : null }, { "systemId" : 20, "count" : 7 } ] } 

您是否可以將您的數據轉換爲這種格式,即使是暫時的?是的,但它意味着一個新的集合:

db.foo.aggregate([ 
    {$match: {modules: {$elemMatch: { "systems": {$elemMatch: {"systemId" : 13}}}}}}, 
    {$unwind : "$modules"}, 
    {$project : {"_id" : 0, "systems" : "$modules.systems"}}, 
    {$out : "flattened_systems"}  
]) 
// confirm the new doc structure 
db.flattened_systems.find() 
{ "_id" : ObjectId("5450e4702127b5e51e8a9e0a"), "systems" : [ { "systemId" : 13, "count" : 2 }, { "systemId" : 20, "count" : 7 }, { "systemId" : 8, "count" : 1 } ] } 
{ "_id" : ObjectId("5450e4702127b5e51e8a9e0b"), "systems" : [ { "systemId" : 13, "count" : 2 }, { "systemId" : 20, "count" : 7 } ] } 

然後,您可以運行上面的更新修改systemIds和重新聚集找回原來的結構:

db.flattened_systems.update(
    { systems: {$elemMatch: {systemId : 13}}}, 
    { $set : {"systems.$" : {d : null}}}, 
    {multi : true} 
); 

db.flattened_systems.aggregate([ 
    {$group : { "_id" : 0, "modules" : {$push : {"systems" : "$systems"}}}}, 
    {$project : {"_id" : 0, "modules" : 1, "flag" : {$literal : "new"}}}, 
    {$out : "processed_systems"}  
]) 

因此, processed_systems現藏有你想要的格式(DOC額外的「新」的標誌是可選的,以顯示你怎麼可能標誌作爲更新):

> db.processed_systems.find() 
{ "_id" : ObjectId("5450e9e92127b5e51e8a9e10"), "modules" : [ { "systems" : [ { "d" : null }, { "systemId" : 20, "count" : 7 }, { "systemId" : 8, "count" : 1 } ] }, { "systems" : [ { "d" : null }, { "systemId" : 20, "count" : 7 } ] } ], "flag" : "new" } 

不理想,particu如果正在積極更新文檔(無法自動完成此操作),但希望它能讓您瞭解如何在此期間進行此操作。我敢肯定,你也可以使用Map Reduce來做到這一點,但將它作爲一個單獨的問題可能會更好。

相關問題