2013-05-25 4 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

звучит так, как будто ваша схема не является хорошим выбором для вашего случая использования. –