我的 mongo DB 有一个具有以下结构的文档:
{'vname':'x', 'pname': 'xyz', 'price': '10000'}
我想获取与
pname='xy'
匹配的所有文档,然后按 vname
进行分组,并将每个 vname
的结果限制为 4。
pipeline = [
{
'$facet': {
'v1': [
{
'$match': {'vname': 'v1'}
},
{
'$sort': {'price': 1}
},
{
'$limit': 4
}
],
'v2': [
{
'$match': {'vname': 'v2'}
},
{
'$sort': {'price': 1}
},
{
'$limit': 4
}
]
}
}
]
docs = Pinfo.objects(pname__icontains='xy').aggregate(pipeline=pipeline)
我看到的另一种方法是为每个
vname
多次运行过滤器查询
docs = Pinfo.objects.filter(Q(pname__icontains='xy')&Q(vname__exact='v1')).limit(4)
还有其他方法可以达到同样的效果吗? 使用聚合和管道方法是更好的方法吗?
你可以尝试一下,
$match
pname
状况$sort
按 pname
升序(可选)$group
通过 vname
并将根对象推入项目中并创建数组$project
显示必填字段并使用 $slice
db.collection.aggregate([
{ $match: { pname: "xy" } },
{ $sort: { pname: 1 } },
{
$group: {
_id: "$vname",
items: { $push: "$$ROOT" }
}
},
{
$project: {
_id: 0,
vname: "$_id",
items: { $slice: ["$items", 4] }
}
}
])
如果您想要根中的所有对象,那么您可以在上面的管道之后添加下面的管道,
$unwind
将项目数组解构为对象$replaceRoot
替换根目录中的项目对象 { $unwind: "$items" },
{ $replaceRoot: { newRoot: "$items" } }
MongoDB 5.2 的更多选项,在
$topN
阶段使用 $group
运算符,
db.collection.aggregate([
{ $match: { pname: "xy" } },
{
$group: {
_id: "$vname",
items: {
$topN: {
output: {
pname: "$pname",
price: "$price"
},
sortBy: { price: 1 },
n: 4
}
}
}
}
])