MongoDB:找到数组中的最小元素并将其删除

时间:2012-11-11 20:15:40

标签: python mongodb pymongo

我在MongoDB中有一个文档,其中一个看起来像这样:

{
"_id" : 100,
"name" : "Something",
"items" : [
    {
        "item" : 47,
        "color" : "red"
    },
    {
        "item" : 44,
        "color" : "green"
    },
    {
        "item" : 39,
        "color" : "blue"
    }
]
}

在每个文档中,我需要找到最小项并删除它。所以它应该是这样的:

{
"_id" : 100,
"name" : "Something",
"items" : [
    {
        "item" : 47,
        "color" : "red"
    },
    {
        "item" : 44,
        "color" : "green"
    }
]
}

看起来应该使用findAndModify函数,但我不能再进一步了。

如何在数组中找到最小元素并将其删除?

我正在使用MongoDB和Pymongo驱动程序。

3 个答案:

答案 0 :(得分:17)

如果您不仅限于查询一步,您可以尝试:

步骤1)使用$ unwind和$ group运算符的聚合函数来查找每个文档的最小项

myresults = db.megas.aggregate( [ { "$unwind": "$items" },  
    {"$group": { '_id':'$_id' , 'minitem': {'$min': "$items.item" } } } ] )

步骤2)循环结果并从数组中拉出元素

for result in myresults['result']:
    db.megas.update( { '_id': result['_id'] }, 
        { '$pull': { 'items': { 'item': result['minitem'] } } } )

答案 1 :(得分:9)

请找到我用普通javascript编写的解决方案。它应该直接通过MongoDb shell

cursor = db.students.aggregate(
[{ "$unwind": "$items" }, 
 { "$match": { "items.color": "green"}},
 { "$group": {'_id': '$_id', 'minitem': {
                '$min': "$items.item"
            }
        }
    }

]);

cursor.forEach(
function(coll) {
    db.students.update({
        '_id': coll._id
    }, {
        '$pull': {
            'items': {
                'item': coll.minitem
            }
        }
    })
})

答案 2 :(得分:0)

Mongo 4.4开始,$function聚合运算符允许应用自定义javascript函数来实现MongoDB查询语言不支持的行为。

并结合Mongo 4.2中对db.collection.update()的改进,可以接受聚合管道,从而允许根据字段自身的值更新字段

我们可以使用语言不容易允许的方式来操纵和更新数组:

// {
//   "name" : "Something",
//   "items" : [
//     { "item" : 47, "color" : "red"   },
//     { "item" : 39, "color" : "blue"  },
//     { "item" : 44, "color" : "green" }
//   ]
// }
db.collection.update(
  {},
  [{ $set:
    { "items":
      { $function: {
          body: function(items) {
            var min = Math.min(...items.map(x => x.item));
            return items.filter(x => x.item != min);
          },
          args: ["$items"],
          lang: "js"
      }}
    }
  }],
  { multi: true }
)
// {
//   "name" : "Something",
//   "items" : [
//     { "item" : 47, "color" : "red"   },
//     { "item" : 44, "color" : "green" }
//   ]
// }

$function具有3个参数:

  • body,这是要应用的函数,其参数是要修改的数组。这里的功能仅在于首先从数组中找到最小的item,然后再filter
  • args,其中包含body函数作为参数的记录中的字段。在我们的情况下,"$items"
  • lang,这是编写body函数的语言。当前仅js可用。