【问题标题】:MongoDB Aggregate and Group by Subcategories of productsMongoDB 按产品的子类别聚合和分组
【发布时间】:2021-11-08 19:45:57
【问题描述】:

我有一个如下所示的 MongoDB 架构

const ProductModel = new Schema({
subcategory: {
    type : mongoose.Schema.Types.ObjectId,
    ref : "Subcategory",
},
product_name: {
    type: String
},
description: {
    type: String
},
price: {
    type: Number
},
});

还有一个子类别架构:

const SubcategoryModel = new Schema({
    subcategoryName: {
        type: String,
    }
});

聚合前的输入查询如下所示:

[
    {
        "_id": "111",
        "subcategory": {
            "_id": "456",
            "categoryName": "Sneakers",
        },
        "product_name": "Modern sneaker",
        "description": "Stylish",
        "price": 4400
    },
    {
        "_id": "222",
        "subcategory": {
            "_id": "456",
            "categoryName": "Sneakers",
        },
        "product_name": "Blue shoes",
        "description": "Vived colors",
        "price": 7500
    },
    {
        "_id": "333",
        "subcategory": {
            "_id": "123",
            "categoryName": "Jackets",
            "__v": 0
        },
        "product_name": "Modern jacket",
        "description": "Stylish",
        "price": 4400
    },
    }
]

查询的最终结果应该是这样的:

{
   "Sneakers":[
      {
         "product_name":"Modern sneaker",
         "description":"Stylish",
         "price":"4400"
      },
      {
         "product_name":"Blue shoes",
         "description":"Vived colors",
         "price":"7500"
      },
      "Jackets":{
         "...."
      }
   ]
}

聚合前的子类:

"subcategories": [
  {
    "_id": "123",
    "categoryName": "Jackets",
    
  },
  {
    "_id": "456",
    "categoryName": "Sneakers",
    
  }
]

我正在尝试填充子类别,然后按产品的 subcategoryName 字段对产品进行分组。

【问题讨论】:

  • 您的数据如何?你能提供一个输入示例吗?
  • 对不起,我刚做了,刷新页面:]
  • sneakersJackets 是来自 subcategoryName 的值?
  • 刚刚添加了一个输入示例和一个输出示例。是的,两者都是 subcategoryName 的值。
  • 你能添加一个子类别的例子吗?

标签: mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

您可以使用此聚合查询:

  • 首先$lookupProductSubcategory 之间进行连接,创建数组subcategories
  • 然后使用$unwind解构数组。
  • $group 通过子产品的名称使用$$ROOT 添加整个对象。
  • 使用$project 传递您想要的字段。
  • replaceRoot 将键值作为SneakersJackets 放入数组中。
db.Product.aggregate([
  {
    "$lookup": {
      "from": "Subcategory",
      "localField": "subcategory.categoryName",
      "foreignField": "categoryName",
      "as": "subcategories"
    }
  },
  {
    "$unwind": "$subcategories"
  },
  {
    "$group": {
      "_id": "$subcategories.categoryName",
      "data": {
        "$push": "$$ROOT"
      }
    }
  },
  {
    "$project": {
      "data": {
        "product_name": 1,
        "description": 1,
        "price": 1
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": {
        "$arrayToObject": [
          [
            {
              "k": "$_id",
              "v": "$data"
            }
          ]
        ]
      }
    }
  }
])

例如here

根据您提供的数据,结果是:

[
  {
    "Sneakers": [
      {
        "description": "Stylish",
        "price": 4400,
        "product_name": "Modern sneaker"
      },
      {
        "description": "Vived colors",
        "price": 7500,
        "product_name": "Blue shoes"
      }
    ]
  },
  {
    "Jackets": [
      {
        "description": "Stylish",
        "price": 4400,
        "product_name": "Modern jacket"
      }
    ]
  }
]

【讨论】:

  • 太好了,您的解决方案确实可以正常工作,但是我遇到了一件额外的事情,假设子类别是 ObjectID 当我尝试提供子类别._id 或 _id 它给了我这个错误 $lookup 参数'localField' 必须是一个字符串,找到 localField: { $toObjectId: "subcategory._id" }: object 你可以检查我在这个链接中对你的解决方案所做的设置mongoplayground.net/p/JH4kUSZWATC
  • 如果字段是 ObjectId 你不需要使用$toObjectId。另外,如果您想解析为 ObjectId,我认为 this query 使用 pipeline 应该可以工作。
  • 谢谢你,这个问题浪费了我很多时间,你救了它;]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-28
  • 2017-01-26
  • 2021-05-19
  • 2013-11-25
  • 1970-01-01
  • 2022-01-26
相关资源
最近更新 更多