2013-08-21 70 views
6

注意:請使用mongodb shell執行代碼。更新/刪除MongoDB集合中的子文檔

比方說,我有一個學生的文件,如下

{ 
    "_id" : 4, 
"grades" : [ 
    { 
     "grade" : 80, 
     "mean" : 75, 
     "std" : 8 
    }, 
    { 
     "grade" : 85, 
     "mean" : 90, 
     "std" : 5 
    }, 
    { 
     "grade" : 85, 
     "mean" : 90, 
     "std" : 5 
    }, 
    { 
     "grade" : 85, 
     "mean" : 95, 
     "std" : 6 
    }, 
    { 
     "grade" : 90, 
     "mean" : 85, 
     "std" : 5 
    } 
] 
} 

我們有2個問題:

問題1:可以說你想與_id = 4個& &等級來更新所有的子文檔。等級= 85 & &等級.std = 5,與std = 6你會寫如下

db.students.update({'$and':[ { _id: 4},{ "grades.grade": 85 }, {"grades.std": 5 } ]}, { $set: { "grades.$.std" : 6 } }); 

現在,如果你執行上面的語句多次(3次),那麼最好就應該更新第二,第三子文檔

但最後一個子文件也得到更新東陽有STD = 5的比賽,但我們給出的條件爲$和不是$或,那麼最後一個文件如何得到更新?

問題2: 現在讓我們假設你想刪除與查詢條件相匹配的子文檔本身。 我嘗試下面的語句

db.students.update({_id:4,'grades.grade':85},{'$unset':{'grades.$':1}}) 

因爲$未設置會把空的子文檔/陣列的情況下,如何解決這個問題?

如何在您的mongodb控制檯中複製?

db.students.insert({ "_id" : 4, "grades" : [ { grade: 80, mean: 75, std: 8 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 90, std: 5 }, { grade: 85, mean: 95, std: 6 }, { grade: 90, mean: 85, std: 5 } ] }); 

回答

10

的「$」操作者只需更新,所以給出的第一場比賽:

db.students.insert({ "_id" : 4, "grades" : [ 
    { grade: 80, mean: 75, std: 8 }, 
    { grade: 85, mean: 90, std: 5 }, 
    { grade: 85, mean: 90, std: 5 }, 
    { grade: 85, mean: 95, std: 6 }, 
    { grade: 90, mean: 85, std: 5 } ]}); 

要更新你需要$elemMatch目標,像這樣:

db.students.update({ _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}}, 
        { $set: { "grades.$.std" : 6 } }); 

然而,你必須符合兩個檔次{"grades.grade": 85, "grades.std": 5}$只更新第一個,因此您需要循環直到全部更新:

db.students.update({ _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}}, 
        { $set: { "grades.$.std" : 6 } }) 
while (db.getLastErrorObj()['n'] > 0) { 
    db.students.update({ _id: 4, "grades": {$elemMatch: {"grade": 85, "std": 5 }}}, 
         { $set: { "grades.$.std" : 6 } }) 
} 

問題2:同樣適用 - 您需要循環到$pull匹配的元素:

db.students.update({_id:4,'grades': {$elemMatch: {'grade':85}}}, {'$pull': {'grades': {'grade':85}}}) 
+0

感謝您的第一個問題的答案,我已經嘗試使用@drmirror答案。 $ pull將在子文檔中設置爲null,那麼我必須執行2更新語句 一個用於更新爲空, 另一個用於從子文檔中刪除null。 一個更新語句可能嗎? –

+0

在2.4中拉取子文件而不是設置爲空。 – Ross

+0

非常抱歉,我的壞...它的工作...非常感謝 –

2

您需要使用$elemMatch來匹配數組內部。 MongoDB中的查詢規則指定對於數組元素的條件,任何條件匹配的任何數組元素都被認爲是匹配的。與$elemMatch,所有條件需要匹配在相同的元素。

+0

你能否寫下相同的shell語句? –

+0

是否可以解決第二個問題? –

+0

謝謝..我用$ elemMatch嘗試,它的工作原理。但對於第二個問題。我不想執行2更新語句只是刪除一個子文檔。是否有辦法?通過一個語句執行 –

0

點符號與任何數組元素中符合條件的文檔匹配。

如果你想匹配只匹配您的所有條件在一個數組元素的文檔(至少),然後爲drmirror已經回答了,你需要使用操作符$ elemMatch,還看到:$elemMatch Operator

在你的情況下,將是:

db.students.update({'$and':[ { _id: 4},{ "grades":{"$elemMatch": {"grade": 85, "std": 5 }}} ]}, { $set: { "grades.$.std" : 6 } }); 

對於你的問題的第二部分,如何刪除數組元素,請參閱以下文章。

In mongoDb, how do you remove an array element by its index

總之,這是一個兩步的操作,第一組到null元素(如你已經這樣做),然後$ pull(S)它關閉。