You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB聚合框架问题:如何按Aisle统计不同产品数量

MongoDB聚合统计每个货架(Aisle)下的不同产品数量

问题场景

订单数据结构示例:

{"_id": {"$oid": "60af57782fbbe971834ae2a6"},"order_id": 2539329,"user_id": 1,"order_number": 1,"order_dow": 2,"order_hour_of_day": 8,"products": [{"product_id": 196,"product_name": "Soda","aisle_id": 77,"aisle": "soft drinks","department_id": 7,"department": "beverages","add_to_cart_order": 1},{"product_id": 12427,"product_name": "Original Beef Jerky","aisle_id": 23,"aisle": "popcorn jerky","department_id": 19,"department": "snacks","add_to_cart_order": 3},{"product_id": 14084,"product_name": "Organic Unsweetened Vanilla Almond Milk","aisle_id": 91,"aisle": "soy lactosefree","department_id": 16,"department": "dairy eggs","add_to_cart_order": 2},{"product_id": 26088,"product_name": "Aged White Cheddar Popcorn","aisle_id": 23,"aisle": "popcorn jerky","department_id": 19,"department": "snacks","add_to_cart_order": 4},{"product_id": 26405,"product_name": "XL Pick-A-Size Paper Towel Rolls","aisle_id": 54,"aisle": "paper goods","department_id": 17,"department": "household","add_to_cart_order": 5}]}

需求是统计每个Aisle下的不同产品数量,但原聚合管道执行失败:

db.orders.aggregate([{"$unwind": "$products"},{"$group": {"_id": {"p_id": "$products.product_id", "p_name": "$products.product_name"}}},{"$project": {"products.aisle_id": 1, "products.aisle": 1}},{"$group": {"_id": {"a_id": "$products.aisle_id", "a_name": "$products.aisle"}, "prod per aisle": {"$sum": 1}}}])

错误原因

第一次$group阶段后,输出文档仅保留了_id(包含产品ID和名称),丢失了products字段及其中的aisle信息,后续$project无法读取不存在的products.aisle_id和products.aisle,导致最终分组无效。

正确实现方式

方式一:先去重产品再按货架统计

通过两次分组,先确保同一产品在同一货架下仅保留一条记录,再按货架统计数量:

db.orders.aggregate([
  // 展开products数组,将每个产品转为独立文档
  {"$unwind": "$products"},
  // 按「产品+货架」维度分组,实现产品去重
  {"$group": {
    "_id": {
      "product_id": "$products.product_id",
      "product_name": "$products.product_name",
      "aisle_id": "$products.aisle_id",
      "aisle": "$products.aisle"
    }
  }},
  // 按货架分组,统计不同产品数量
  {"$group": {
    "_id": {
      "aisle_id": "$_id.aisle_id",
      "aisle": "$_id.aisle"
    },
    "distinct_product_count": {"$sum": 1}
  }},
  // 可选:调整输出格式,优化可读性
  {"$project": {
    "_id": 0,
    "aisle_id": "$_id.aisle_id",
    "aisle_name": "$_id.aisle",
    "distinct_product_count": 1
  }}
])

方式二:用$addToSet收集去重产品再统计

利用$addToSet自动去重的特性,直接按货架收集所有不重复的产品ID,再通过$size计算数量:

db.orders.aggregate([
  // 展开products数组
  {"$unwind": "$products"},
  // 按货架分组,收集该货架下所有不重复的产品ID
  {"$group": {
    "_id": {"aisle_id": "$products.aisle_id", "aisle": "$products.aisle"},
    "distinct_product_ids": {"$addToSet": "$products.product_id"}
  }},
  // 计算产品ID集合的大小,即为不同产品数量
  {"$project": {
    "_id": 0,
    "aisle_id": "$_id.aisle_id",
    "aisle_name": "$_id.aisle",
    "distinct_product_count": {"$size": "$distinct_product_ids"}
  }}
])

两种方式都能实现需求,方式二更简洁高效,适合大多数场景。

内容的提问来源于stack exchange,提问作者Carlo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:56:01