2

给定一个集合,例如:

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

我正在寻找一种更有效的方法,使用更新命令 $pull/remove 匹配的元素并使用 $each 修饰符 $push 来插入新元素。但是我很难找到要执行推送操作的数组的 $position。另一个需要注意的是,我想为新水果保留旧水果的位置。即第一个新水果将与旧水果具有相同的位置。

4

1 回答 1

3

push and pull同一命令中相同键的MongoDB 更新无法正常工作,请检查此

所以首先你应该pull使用 这个命令bananasfruits数组中

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

首先true对于像这样的多个文档,它从数组中{multi:true}拉出,然后使用这样的方法将香蕉替换为“樱桃”和“日期” :bananasfruits$push

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

编辑

如果您只想插入那些包含的文档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插入位置,bananas则首先找出bananas数组中的位置,但这不可能直接使用 mongo 查询,因此这里使用了一些脚本代码(这里我使用了 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运算符将元素插入到数组的末尾。

于 2015-08-17T11:00:40.123 回答