MongoDB:子阵列的Update属性只更新第一个元素

时间:2013-05-25 14:12:27

标签: node.js mongodb mongodb-update

匹配元素如下所示:

{
    "_id": {
        "$oid": "519ebd1cef1fce06f90e3157"
    },
    "from": "Tester2",
    "to": "Tester",
    "messages": [
        {
            "username": "Tester2",
            "message": "heeey",
            "read": false
        },
        {
            "username": "Tester",
            "message": "hi!",
            "read": false
        },
        {
            "username": "Tester2",
            "message": "test",
            "read": false
        }
    ],
}

现在我尝试将read属性设置为用户名不等于Tester的子元素的当前日期:

var messages = db.collection('messages');
messages.update(
{
    _id: new BSON.ObjectID("519ebd1cef1fce06f90e3157"),
    messages: {
        $elemMatch: { username: { $ne: "Tester" } }
    }
},
{ $set: { 'messages.$.read': new Date() } },
{ multi: true }, function(error, result) {
    console.log(error);
    console.log(result);
});

但只是第一个消息子元素read属性更新:

{
    "_id": {
        "$oid": "519ebd1cef1fce06f90e3157"
    },
    "from": "Tester2",
    "to": "Tester",
    "messages": [
        {
            "username": "Tester2",
            "message": "heeey",
            "read":  {
                "$date": "2013-01-01T00:00:00.000Z"
            }
        },
        {
            "username": "Tester",
            "message": "hi!",
            "read": false
        },
        {
            "username": "Tester2",
            "message": "test",
            "read": false
        }
    ],
}

代码有什么问题? 我正在使用node.js v0.10.8和MongoDB v2.4.3以及node-mongodb-native

3 个答案:

答案 0 :(得分:10)

你的代码没有错; $ operator包含第一个匹配数组元素的索引。 {multi: true}选项仅使update适用于多个文档,而不是数组元素。要在单个update中更新多个数组元素,必须通过数字索引指定它们。

所以你必须做这样的事情:

messages.update(    
    {
        _id: new BSON.ObjectID("519ebd1cef1fce06f90e3157")
    },
    { $set: { 
        'messages.0.read': new Date(),
        'messages.2.read': new Date()
    } },
    function (err, result) { ... }
);

答案 1 :(得分:1)

这类似于问题:How to Update Multiple Array Elements in mongodb

var set = {}, i, l;
for(i=0,l=messages.length;i<l;i++) {
  if(messages[i].username != 'tester') {
    set['messages.' + i + '.read'] = new Date();
  }
}

.update(objId, {$set:set});

答案 2 :(得分:0)

我认为在这种情况下可以使用ArrayFilters