【问题标题】:mongodb: replace an element in an array with one or more elementsmongodb:用一个或多个元素替换数组中的元素
【发布时间】:2015-11-09 22:19:46
【问题描述】:

给定一个集合,例如:

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

我想用“cherries”和“dates”替换所有“bananas”实例。所以结果集合将是:

{
   _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 匹配的元素并使用 $each 修饰符 $push 来插入新元素。但是我很难找到要执行推送操作的数组的 $position。另一个需要注意的是,我想为新水果保留旧水果的位置。即第一个新水果将与旧水果具有相同的位置。

【问题讨论】:

    标签: mongodb pymongo pymongo-3.x


    【解决方案1】:

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

    所以首先你应该使用这个命令从fruits数组中pull所有bananas

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

    首先true 用于多个文档,例如{multi:true},因此它从fruits 数组中提取和bananas,然后使用$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 运算符会将元素插入到数组的末尾。

    【讨论】:

    • $push 命令会将“cherries”和“dates”附加到集合中的所有文档中。这可以通过先在查询中使用“香蕉”执行 $push 然后执行 $pull 来避免。但这仍然不会保留职位。
    • 据我了解,您想将cherries and dates 推入bananas 位置并拉动bananas 对吗?
    • 检查新编辑的答案我不知道pymongo所以我发布了Java脚本。
    • 只需要提供$position 修饰符。但我不知道如何找到bananas 的位置。
    • mongoDB 仍然没有提供任何运算符来找出数组元素的位置检查这个jira issuethis also 所以你需要在我的second edit 中使用脚本找出元素的位置我使用了 java 脚本使用indexOf("bananas")方法找出位置
    猜你喜欢
    • 2017-07-05
    • 2018-07-23
    • 1970-01-01
    • 2019-12-20
    • 2013-07-04
    • 1970-01-01
    • 2021-09-29
    • 2019-03-30
    • 1970-01-01
    相关资源
    最近更新 更多