Подтвердить что ты не робот

Удалить поле из всех элементов массива в mongodb

У меня есть документ ниже в MongoDB (2.4.5)

{
    "_id" : 235399,
    "casts" : {
        "crew" : [ 
            {
                "_id" : 1186343,
                "withBase" : true,
                "department" : "Directing",
                "job" : "Director",
                "name" : "Connie Rasinski"
            },
            {
                "_id" : 86342,
                "withBase" : true
            }
        ]
    },
    "likes" : 0,
    "rating" : 0,
    "rating_count" : 0,
    "release_date" : "1955-11-11"
}

Я хочу удалить withBase, поданный из элементов массива внутри casts.crew..

Я пробовал это

db.coll.update({_id:235399},{$unset: {  "casts.crew.withBase" : 1 } },false,true)

ничего не изменилось.

И попробовал это..

db.coll.update({_id:235399},{$unset: {  "casts.crew" : { $elemMatch: { "withBase": 1 } } } },false,true)

он удалил весь массив экипажа из документа.

Может кто-нибудь, пожалуйста, предоставит мне правильный запрос?

4b9b3361

Ответ 1

Извините, что разочаровал вас, но ваш ответ

db.coll.update({
   _id:235399,
   "casts.crew.withBase": {$exists: true}
},{
   $unset: {
      "casts.crew.$.withBase" : true
   }
},false,true)

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

оператор positional $действует как заполнитель для первого элемента который соответствует документу запроса

Вы также не можете использовать $unset (как вы пробовали раньше), потому что он не может работать с массивами (и вы в основном пытаетесь удалить ключ из документа из массива). Вы также не можете удалить его с помощью $pull, потому что pull удаляет весь массив, а не только его поле.

Поэтому, насколько я знаю, вы не можете сделать это с помощью простого оператора. Поэтому последнее средство делает $find, а затем forEach с сохранением. Вы можете увидеть как это сделать в моем ответе здесь. В вашем случае вам нужно иметь еще один цикл в функции forEach для итерации по массиву и удалить ключ. Я надеюсь, что вы сможете изменить его. Если нет, я постараюсь вам помочь.

P.S. Если кто-то ищет способ сделать это - вот функция Сандры

db.coll.find({_id:235399}).forEach( function(doc) {
  var arr = doc.casts.crew;
  var length = arr.length;
  for (var i = 0; i < length; i++) {
    delete arr[i]["withBase"];
  }
  db.coll.save(doc);
});

Ответ 2

Я нашел способ отключить эти списки, не вытягивая объект (это означает, что он просто выполняет обновление), он довольно хакерский, но если у вас есть огромная база данных, он заключит сделку:

db.coll.update({},{$unset: {"casts.crew.0.withBase" : 1, "casts.crew.1.withBase" : 1} }, {multi: 1})

Другими словами, вам нужно рассчитать, сколько объектов может быть в любом из ваших списков документов и явно добавить эти числа, в этом случае как {casts.crew.NUMBER.withBase: 1}.

Кроме того, чтобы подсчитать самый длинный массив в объекте mongodb, можно сделать агрегат, например:

db.coll.aggregate( [   { $unwind : "$casts.crew" },   { $group : { _id : "$_id", len : { $sum : 1 } } },   { $sort : { len : -1 } },   { $limit : 1 } ], {allowDiskUse: true} )

Просто хочу подчеркнуть, что это не просто решение, но способ быстрее, чем выборка и сохранение.

Ответ 3

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

Что-то вроде

 db.coll.update( {_id:235399}, {$unset: {"casts.crew.$[].withBase":""}} )

$[] удаляет все свойство withBase из массива crews. Он выступает в качестве заполнителя для обновления всех элементов в массиве.

Использовать multi true для воздействия на несколько документов.