2013-11-13 4 views
27

У меня есть ниже документа в MongoDB (2.4.5)Удалить поле из всех элементов массива в MongoDB

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

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

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

ответ

33

Жаль разочаровать вас, но ваш ответ

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

не является правильным. На самом деле это будет удалить значение, но только с первым вхождением поддокумента, из-за способом positional operator works:

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

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

Поэтому, насколько я знаю, вы не можете сделать это с помощью простого оператора. Поэтому последнее средство делает $find, а затем forEach с сохранением. Вы можете увидеть how to do this in my answer here. В вашем случае вам нужно иметь еще один цикл в функции forEach для итерации по массиву и до delete a key. Я надеюсь, что вы сможете изменить его. Если нет, я постараюсь вам помочь.

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); 
}); 
+1

Большое спасибо Сальвадору. Он работал. Вот моя функция 'db.coll.find ({_ id: 235399}). ForEach (function (doc) { var arr = doc.casts.cast; var length = arr.length; для (var i = 0; i Nancy

+0

Рад, что это помогло. Я добавлю его в свой ответ с вашими учетными данными. –

+1

Более функциональный подход к решению Нэнси является: 'db.coll.find ({_ ID: 235399}). Foreach (функция (док) { doc.casts.crew.forEach (функция (экипаж) { удалить команду .withBase; }) db.coll.save (doc); }); ' –

11

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

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}) 

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

7

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

Что-то вроде

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

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

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

+1

Пожалуйста, не используйте нисходящее движение без объяснения причин. Будем рады ответить на ваши вопросы. – Veeram

+1

Извините, что я ниспроверг это, я не могу спустить вниз :) - это на самом деле работает _does_, но только для mongodb> = 3.6. И он также работает с 'updateMany()' – mils

+1

@mils Добавлена ​​версия в ответ. – Veeram

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