【问题标题】:MongoDB limit group by resultsMongoDB 按结果限制分组
【发布时间】:2020-11-01 09:01:15
【问题描述】:

我的 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)

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

【问题讨论】:

    标签: mongodb aggregation-framework mongoengine


    【解决方案1】:

    你可以试试,

    • $matchpname条件
    • $sort by pname 升序(可选)
    • $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 将 items 数组解构为对象
    • $replaceRoot 替换根目录下的 items 对象
      { $unwind: "$items" },
      { $replaceRoot: { newRoot: "$items" } }
    

    Playground

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 2016-04-01
      • 1970-01-01
      相关资源
      最近更新 更多