mongodb:用一个或多个元素替换数组中的一个元素

mongodb: replace an element in an array with one or more elements

给定一个集合,例如:

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

我想将 "bananas" 中的所有实例替换为 "cherries" 和 "dates"。因此生成的集合将是:

{
   _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 命令将 $pull/remove 匹配的元素和 $push 与 $each 修饰符一起插入新元素。但是我很难找到要执行推送操作的数组的 $position 。另一个警告是我想为新水果保留旧水果的位置。即第一个新水果将与旧水果具有相同的位置。

MongoDB 更新 push and pull 相同命令中的相同键不适用于更多 check this.

所以首先你应该 pull 来自 fruits 数组的所有 bananas 使用这个命令

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

首先 true 用于 {multi:true} 等多个文档,因此它从 fruits 数组中提取 bananas,然后添加香蕉替换为 "cherries" 和"dates" 像这样使用 $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 运算符会将元素插入到数组的末尾。