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

时间:2013-08-21 10:06:28

标签: 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
    }
]
}

我们有两个问题:

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

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

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

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

问题2: 现在假设您要删除与查询条件匹配的子文档。 我尝试了以下声明

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

因为$ 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 } ] });

4 个答案:

答案 0 :(得分: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}}})

答案 1 :(得分:2)

您需要使用$elemMatch来匹配数组内部。 MongoDB中的查询规则指定对于数组元素的条件,任何条件匹配的任何数组元素都被视为匹配。使用$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)它。

答案 3 :(得分:0)

对于问题#1,请参阅:https://stackoverflow.com/a/20601288/773953

基本上你必须构建你想手动设置的数组。