更新/删除MongoDB集合中的子文档

May*_*ria 6 mongodb mongodb-query mongodb-update

注意:请使用mongodb shell执行代码.

假设我有一份学生证件,如下所示

{
    "_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
    }
]
}
Run Code Online (Sandbox Code Playgroud)

我们有两个问题:

问题1:假设你想用_id = 4 && grades.grade = 85 && grades.std = 5更新所有子文档,std = 6你会写如下

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

现在,如果您多次执行上述语句(3次),那么理想情况下它应该更新第2个,第3个子文档

但是最后一个子文档也因为std = 5匹配而得到更新,但我们已经给出条件为$而不是$或者,那么最后一个文档是如何更新的呢?

问题2: 现在假设您要删除与查询条件匹配的子文档本身.我试着跟随声明

db.students.update({_id:4,'grades.grade':85},{'$unset':{'grades.$':1}})
Run Code Online (Sandbox Code Playgroud)

因为$ unset会在子文档/数组的情况下放置null,如何解决这个问题呢?

如何在你的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 } ] });
Run Code Online (Sandbox Code Playgroud)

Ros*_*oss 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 } ]});
Run Code Online (Sandbox Code Playgroud)

要更新,您需要$elemMatch像这样定位:

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

但是,你必须符合两个等级{"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 } })
}
Run Code Online (Sandbox Code Playgroud)

问题2:同样的事情适用 - 你需要循环到$pull匹配的元素:

db.students.update({_id:4,'grades': {$elemMatch: {'grade':85}}}, {'$pull': {'grades': {'grade':85}}})
Run Code Online (Sandbox Code Playgroud)