【问题标题】:MongoDB group to get min value of a field & it's respective dataMongoDB组获取字段及其各自数据的最小值
【发布时间】:2020-04-28 11:36:38
【问题描述】:

我有一系列这样的产品:

[
  {
    productName: "productB",
    productImage: "http://some.url/product_B.jpg",
    productCategoryId: 34,
    productPrice: 10
  },
  {
    productName: "productA",
    productImage: "http://some.url/product_A.jpg",
    productCategoryId: 34,
    productPrice: 50
  }
]

到目前为止,我有以下内容:

db.local.aggregate(
   [
      {
         "$match":{
            "productCategoryId":34
         }
      },
      {
         "$facet":{
            "byCategory":[
               {
                  "$group":{
                     "_id":"productCategory",
                     "minprice":{
                        "$min":"$productPrice"
                     }
                  }
               }
            ]
         }
      }
   ]
)

我需要按单个字段(类别)聚合/分组并获得每个类别的最低价格,但我还想返回文档的产品名称和图像(其他 2 个字段)以及每个字段的最低价格类别。任何人都可以指出一些方向或例子吗? groupBy 和 min 被覆盖,只是提取额外信息的部分。 更新了我已经拥有的架构和聚合,@PulkitAgg1010 我希望通过每个类别的 minPrice 来获取 productImage 和 productPrice 记录。

【问题讨论】:

标签: mongodb mongodb-query aggregation-framework


【解决方案1】:

你可以使用下面的聚合

db.collection.aggregate([
  { "$group": {
    "_id": "$productCategory",
    "doc": {
      "$min": {
        "minprice": "$productPrice",
        "productName": "$productName",
        "productCategory": "$productCategory"
      }
    }
  }},
  { "$replaceRoot": { "newRoot": "$doc" }}
])

$min 总是取对象内部传递的第一个表达式的最小值。这就是价值。

【讨论】:

    【解决方案2】:

    您可能不需要为此使用$facet,请尝试以下查询:

    db.collection.aggregate([
        { "$match": { "productCategoryId": 34 } },
        /** group on `productCategoryId` & get `minprice` on all docs & also push all docs into data array, 
         * Also you'll only have `"productCategoryId": 34` so need not to say ``"_id": "$productCategoryId"  in group */
        {
          "$group": { "_id": "$productCategoryId", "minprice": { "$min": "$productPrice" }, data: { $push: "$$ROOT" } }
        },
        /** unwind data array */
        { $unwind: "$data" },
        /** match the docs which have `data.productPrice` equivalent to `minprice` - 
         * If there are multiple matches you can use `$limit` after match stage to limit result */
        {
          $match: {  $expr: { $eq: [ "$data.productPrice", "$minprice" ] } }
        },
        /** make `data` as new root of doc */
        { $replaceRoot: {  newRoot: "$data" } }
      ])
    

    测试: mongoplayground

    如果您认为要处理的文档太多$unwind,请尝试以下查询:

    db.collection.aggregate([
        { "$match": { "productCategoryId": 34 } },
        /** group on `productCategoryId` & get `minprice` on all docs & also push all docs into data array */
        {
          "$group": { "_id": "$productCategoryId", "minprice": { "$min": "$productPrice" }, data: { $push: "$$ROOT" } }
        },
        /** re-create `data` array with matched docs */
        { $project: { data: { $filter: { input: "$data", cond: { $eq: [  "$$this.productPrice",  "$minprice" ] } } } } },
        /** unwind data array */
        { $unwind: "$data" },
        /** make `data` as new root of doc */
        { $replaceRoot: {  newRoot: "$data" } }
      ])
    

    测试: mongoplayground

    【讨论】:

      猜你喜欢
      • 2011-11-19
      • 2015-10-31
      • 1970-01-01
      • 1970-01-01
      • 2023-01-01
      • 2018-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多