MongoDB 按结果限制分组

MongoDB limit group by results

我的 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'}
                },
                {
                    '$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)

还有其他方法可以达到同样的效果吗? 使用聚合和管道方法是否更好?

你可以试试,

  • $matchpname条件
  • $sortpname 升序排列(可选)
  • $group by vname 并将根对象推入项目并制作数组
  • $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 替换根目录中的项目对象
  { $unwind: "$items" },
  { $replaceRoot: { newRoot: "$items" } }

Playground