6

注意:请使用 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 && grades.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 匹配,但是我们给出的条件是$ 而不是$or,那么最后一个文档怎么会更新呢?

问题 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

4 回答 4

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}}})
于 2013-08-21T12:36:44.230 回答
2

您需要使用$elemMatch来匹配数组内部。MongoDB 中的查询规则指定对于数组元素的条件,任何条件匹配的任何数组元素都被视为匹配。使用$elemMatch,所有条件都需要在同一个元素上匹配。

于 2013-08-21T11:17:53.777 回答
0

点表示法匹配其条件可以在任何数组元素中满足的文档。

如果您只想匹配与一个数组元素中的所有条件匹配的文档(至少),那么由于drmirror已经回答,您需要使用运算符 $ elemMatch,另请参见:$elemMatch 运算符

在你的情况下,这将是:

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

对于您问题的第二部分,如何删除数组元素,请参阅以下帖子。

在 mongoDb 中,如何通过索引删除数组元素

简而言之,这是一个两步操作,首先设置null元素(就像你已经做的那样),然后它 $ pull(s) 它关闭。

于 2013-08-21T12:32:59.107 回答
0

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

本质上,您必须构建您想要手动设置的数组。

于 2014-03-11T14:50:59.470 回答