我在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驱动程序。
答案 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
可用。