2015-08-17 4 views
0

данной коллекции, такие как:MongoDB: заменить элемент в массиве с одним или несколькими элементами

{ 
    _id: 1, 
    fruits: [ "apples", "pears", "oranges", "grapes", "bananas" ], 
} 
{ 
    _id: 2, 
    fruits: [ "plums", "kiwis", "oranges"], 
} 
{ 
    _id: 3, 
    fruits: [ "plums", "kiwis", "oranges", "bananas", "apples" ], 
} 

Я хочу, чтобы заменить все экземпляры «бананы» в «с вишней» и «даты». Таким образом, в результате коллекция будет:

{ 
    _id: 1, 
    fruits: [ "apples", "pears", "oranges", "grapes", "cherries", "dates"], 
} 
{ 
    _id: 2, 
    fruits: [ "plums", "kiwis", "oranges"], 
} 
{ 
    _id: 3, 
    fruits: [ "plums", "kiwis", "oranges", "cherries", "dates", "apples"], 
} 

Один метод, который я использовал через PyMongo:

for document in db.collection.find({'fruits':'bananas'}): 
 
    fruits_list = document['fruits'] 
 
    new_fruits_list = [] 
 
    for fruit in fruit_list: 
 
    if fruit != 'bananas': 
 
     new_fruit_list.append(fruit) 
 
    else: 
 
     for new_fruit in ['cherries','dates']: 
 
     new_fruit_list.append(new_fruit) 
 

 
    db.collection.update({'_id' : document['_id']}, {'$set' : {'fruits' : new_fruit_list}})

Я ищу для более эффективного метода, используя update команду $ тянуть/удалите согласованный элемент и $ push с $ каждым модификатором, чтобы вставить новые элементы. Но я нахожусь в положении нахождения $ -го положения массива, в котором должны выполняться операции push. Еще одно предостережение в том, что я хочу сохранить позиции старых фруктов для новых фруктов. то есть первые новые фрукты будут иметь такое же положение, как и старые плоды.

ответ

0

Обновление MongoDB для push and pull за тот же ключ в той же команде не работает для более check this.

Итак, сначала вы должны pull все bananas из fruits массива с помощью этой команды

db.collection.update({},{"$pull":{"fruits":"bananas"}},true,false) 

Первый true для нескольких документов, как {multi:true} так тянуть и bananas из fruits массива, а затем добавить замену бананов, как «вишня» и "дата", используя $push так:

db.collection.update({},{"$push":{"fruits":{"$each":["cherries","dates"]}}},true,true) 

EDIT

Если вы хотите тонный вставить только те документы, содержит bananas то первый толчок, а затем тянуть, как это:

db.collection.update({"fruits":{"$in":["bananas"]}},{"$push":{"fruits":{"$each":["cherries","dates"]}}},true,true) 

, а затем вытащить bananas:

db.collection.update({"fruits":{"$in":["bananas"]}},{"$pull":{"fruits":"bananas"}},true,true) 

Второй Редактировать

Если cherries and dates вставляется с pos ition bananas затем сначала выяснить позицию bananas в массиве, но это не представляется возможным непосредственно с Монго запроса так что здесь используется некоторый скриптовый код (здесь я использовал JavaScript) с помощью mongo bulk будет обновлять документы проверить код ниже:

var bulk = db.collectionName.initializeOrderedBulkOp(); 
var counter = 0; 
db.collectionName.find({"fruits":{"$in":["bananas"]}}).forEach(function(data){ 
var postion = data.fruits.indexOf("bananas"); 
    bulk.find({"_id":data._id}).updateOne({"$push":{"fruits":{"$each":["cherries","dates"],"$position":postion}}},true,true); 
    bulk.find({"_id":data._id}).updateOne({"$pull":{"fruits":"bananas"}},true,true); 
    counter++; 
if (counter % 1000 == 0) { 
      bulk.execute(); 
      bulk = db.collectionName.initializeOrderedBulkOp(); 
     } 
}); 

if (counter % 1000 != 0){ 
    bulk.execute(); 
} 

$postion модификатора определяет местоположение в массиве, в котором элементы ввода $push. Без модификатора $position оператор $push вставляет элементы в конец массива.

+0

Команда $ push добавит «вишни» и «даты» ко всем документам в коллекции. Этого можно избежать, выполнив $ push сначала, используя «бананы» в запросе, а затем выполнив $ pull. Но это все равно не сохранит позиции. – gnub

+0

Как я понимаю, вы хотите нажать «вишни и даты» в положение «бананы» и потянуть «бананы» вправо? – Yogesh

+0

есть. вот что я хочу делать. – gnub

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