Добавить новое поле ко всем документам во вложенном массиве - PullRequest
9 голосов
/ 13 марта 2012

У меня есть база данных личных документов.У каждого есть поле с именем photos, которое представляет собой массив фотодокументов.Я хотел бы добавить новый флажок «проверено» к каждому документу с фотографиями и инициализировать его как false.

Это запрос, который я пытаюсь использовать:

db.person.update({ "_id" : { $exists : true } }, {$set : {photos.reviewed : false} }, false, true)

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

SyntaxError: missing : after property id (shell):1

Возможно ли это, и если да, что я делаю не так в своем обновлении?

Вот полный пример документа 'person':

{
"_class" : "com.foo.Person",
"_id" : "2894",
"name" : "Pixel Spacebag",
"photos" : [
    {
        "_id" : null,
        "thumbUrl" : "http://site.com/a_s.jpg",
        "fullUrl" : "http://site.com/a.jpg"
    },
    {
        "_id" : null,
        "thumbUrl" : "http://site.com/b_s.jpg",
        "fullUrl" : "http://site.com/b.jpg"
    }]
}

Бонусная карма для тех, кто может подсказать мне, почему уборщик обновляет «все документы», не используя запрос { "_id" : { $exists : true } }

Ответы [ 5 ]

8 голосов
/ 13 марта 2012

Возможно ли это, и если да, что я делаю не так в своем обновлении?

Нет. В общем, MongoDB хорош только для обновления объектов верхнего уровня.

Исключением здесь является позиционный оператор $ . Из документов: Use this to find an array member and then manipulate it.

Однако в вашем случае вы хотите изменить все элементы в массиве. Так что это не то, что вам нужно.

Бонусная карма для тех, кто может подсказать мне, зачем обновлять «все документы»

Попробуйте db.coll.update(query, update, false, true), это приведет к обновлению "multi". Этот последний true делает его мульти.

Возможно ли это,

У вас есть два варианта:

  1. Напишите цикл for для выполнения обновления. В основном это будет вложенный цикл for, один для циклического прохождения данных, другой для циклического прохождения подмассива. Если у вас много данных, вы можете написать, что это ваш драйвер ( и, возможно, многопоточный ).
  2. Введите свой код для обработки reviewed как обнуляемый. Запишите данные так, чтобы, если они встретят фотографию с reviewed undefined, это должно быть false. Затем вы можете соответствующим образом установить поле и зафиксировать его обратно в БД.

Метод №2 - это то, к чему вы должны привыкнуть. По мере того как ваши данные растут и вы добавляете поля, становится все труднее "перенести" все старые данные. Это похоже на проблему выдачи изменения схемы в SQL, когда в базе данных есть элементы размером 1B.

Вместо этого просто сделайте ваш код устойчивым к null и научитесь обращаться с ним по умолчанию.

Опять же, это все еще не решение, которое вы ищете.

6 голосов
/ 20 апреля 2018

Для тех, кто все еще ищет ответ, это возможно с MongoDB 3.6 с полным позиционным оператором $[], см. документы :

db.getCollection('person').update(
   {},
   { $set: { "photos.$[].reviewed" : false } },
   { multi: true}
)
0 голосов
/ 07 сентября 2015

Старая тема сейчас, но она отлично работала с Mongo 3.0.6:

db.users.update({ _id: ObjectId("55e8969119cee85d216211fb") }, { $set: {"settings.pieces": "merida"} })

В моем случае пользовательская сущность выглядит как

{ _id: 32, name: "foo", ..., settings: { ..., pieces: "merida", ...} }
0 голосов
/ 13 мая 2014

Вы можете сделать так:

db.person.update({}, $set:{name.surname:null}, false, true);
0 голосов
/ 14 августа 2012

Вы можете сделать это

(null, {$set : {"photos.reviewed" : false} }, false, true)

Первый параметр имеет значение null: спецификация отсутствует = любой элемент в коллекции.

"photos.reviewed" должен быть объявлен как строка для обновления подполя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...