MongoDB限制结果分组

问题描述

我的mongo数据库的文档结构如下:

{'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'}
                },{
                    '$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条件
  • $sortpname升序排列(可选)
  • $groupvname,并在项目中推送根对象并创建数组
  • $project以显示必填字段,并使用$slice
  • 获得4个对象
db.collection.aggregate([
  { $match: { pname: "xy" } },{ $sort: { pname: 1 } },{
    $group: {
      _id: "$vname",items: { $push: "$$ROOT" }
    }
  },{
    $project: {
      _id: 0,vname: "$_id",items: { $slice: ["$items",4] }
    }
  }
])

Playground


如果要在根目录中包含所有对象,则可以在上述管道之后添加以下管道,

  • $unwind将项数组解构为对象
  • $replaceRoot替换root中的项目对象
  { $unwind: "$items" },{ $replaceRoot: { newRoot: "$items" } }

Playground

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...