2013-05-25 73 views
0

匹配的元素看起来像这样:的MongoDB:子阵的更新酒店刚刚更新的第一个元素

{ 
    "_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

回答

6

你的代码没有问题; $ 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) { ... } 
); 
+0

好吧,如果我不知道以前的指数?我不能简单地使用'messages。$。read'? – David

+1

你需要做一个单独的查询来获取所有的消息,这样你才能确定索引(显然是一种痛苦)。 '$'将会是0(第一个匹配元素的索引),所以它只会引用第一个元素。简而言之,MongoDB并不真正支持你想要做的事情。 – JohnnyHK

+0

听起来像是你的模式不适合你的用例。 –