2014-01-09 3 views
1

у меня есть данные, которые выглядят, как это в моей базе данныхКак нажимать словарь на вложенный массив с помощью mongodb?

> db.whocs_up.find() 
{ "_id" : ObjectId("52ce212cb17120063b9e3869"), "project" : "asnclkdacd", "users" : [ ] } 

и я попытался добавить к массиву 'пользователей, как так:

> db.whocs_up.update({'users.user': 'usex', 'project' : 'asnclkdacd' },{ '$addToSet': { 'users': {'user':'userx', 'lastactivity' :2387843543}}},true) 

, но я получаю следующее сообщение об ошибке:

Cannot apply $addToSet modifier to non-array 

То же самое происходит с оператором push, что я делаю неправильно? им на 2.4.8

я пытался следовать этому примеру отсюда: MongoDB - Update objects in a document's array (nested updating)

db.bar.update({user_id : 123456, "items.item_name" : {$ne : "my_item_two" }} , 
      {$addToSet : {"items" : {'item_name' : "my_item_two" , 'price' : 1 }} } , 
      false , 
      true) 

питон тег, потому что я работал с питоном, когда я столкнулся с этим, но это Nto работает на монго оболочки, как вы можете увидеть

EDIT ============================== получил его на работу

очевидно, если я изменяю обновление от

db.whocs_up.update({'users.user': 'usex', 'project' : 'asnclkdacd' },{ '$addToSet': { 'users': {'user':'userx', 'lastactivity' :2387843543}}},true) 

к этому:

db.whocs_up.update({'project' : 'asnclkdacd' },{ '$addToSet': { 'users': {'user':'userx', 'lastactivity' :2387843543}}},true) 

это работает, но может кто-нибудь объяснить, почему два не достичь того же, в моем понимании, они должны ссылаться на тот же документ, и, следовательно, сделать то же самое , Что добавляет 'users.user': 'userx' изменить в своем обновлении? ссылается ли он на какой-то внутренний документ в массиве, а не на документ в целом?

ответ

2

Это известная ошибка в MongoDB (SERVER-3946). В настоящее время обновление с $push/$addToSet с запросом в том же поле не работает должным образом.

В общем случае, есть несколько обходных путей:

  1. Restructure ваша операция обновления не должны запрашивать на поле, которое также будет обновляться с помощью $push/$addToSet (как вы сделали выше).
  2. Используйте оператор $all в запросе, поставляя однозначный массив, содержащий значение поиска. например вместо этого:

    db.foo.update({ x : "a" }, { $addToSet : { x : "b" } }, true) 
    

    сделать это:

    db.foo.update({ x : { $all : ["a"] } }, { $addToSet : { x : "b" } } , true) 
    

В вашем конкретном случае, я думаю, вам нужно заново оценить работу, которую вы пытаетесь сделать. Операция обновления, которую вы указали выше, добавит новую запись массива для каждой уникальной пары (user, lastactivity), которая, вероятно, не является тем, что вы хотите. Я предполагаю, что вы хотите уникальную запись для каждого пользователя.

следует изменить схему таким образом, что у вас есть один документ для каждого пользователя:

{ 
    _id : "userx", 
    project : "myproj", 
    lastactivity : 123, 
    ... 
} 

Операция обновления становится чем-то вроде:

db.users.update({ _id : "userx" }, { $set : { lastactivity : 456 } }) 

Всех пользователей в данном проекте может все еще ищутся эффективно, добавив вторичный индекс в проект.

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

Смежные вопросы