Mongodb 管道之 $bucket和 $facet 用法详解

前言

在MongoDB的聚合框架中,管道 $bucket$facet 是两个功能强大的阶段操作符,分别用于数据的分组和多维度聚合。
以下是它们的详细说明及对比:


一. 用法详解

1. $bucket

功能:将文档按指定表达式的结果分组到预定义的区间(桶)中,适用于单维度范围分组。

语法
{
  $bucket: {
    groupBy: <expression>,      // 分组的依据表达式
    boundaries: [<lower1>, <lower2>, ...], // 桶的边界值(必须有序且递增)
    default: <literal>,         // 未命中任何桶的文档的默认分类
    output: {                   // 每个桶的输出字段
      <field1>: { <accumulator> },
      ...
    }
  }
}
示例

将订单按金额分桶:

db.orders.aggregate([
  {
    $bucket: {
      groupBy: "$amount",
      boundaries: [0, 50, 100, 200],
      default: "200+",
      output: {
        count: { $sum: 1 },
        total: { $sum: "$amount" }
      }
    }
  }
]);

输出

[
  { "_id": 0, "count": 5, "total": 250 },
  { "_id": 50, "count": 8, "total": 600 },
  { "_id": 100, "count": 3, "total": 450 },
  { "_id": "200+", "count": 2, "total": 500 }
]
注意事项:
  • boundaries必须严格递增。
  • 未匹配且未设置default的文档会被丢弃。
  • 每个桶的_id对应区间的下限。

2. $facet

功能:在同一聚合阶段内并行执行多个独立的子管道,输出多维度的聚合结果。

语法
{
  $facet: {
    <outputField1>: [<pipeline1>],  // 子管道1
    <outputField2>: [<pipeline2>],  // 子管道2
    ...
  }
}
示例

同时统计价格区间和地区销售额:

db.orders.aggregate([
  {
    $facet: {
      "priceRanges": [
        {
          $bucket: {
            groupBy: "$amount",
            boundaries: [0, 50, 100, 200],
            default: "200+",
            output: { count: { $sum: 1 }, total: { $sum: "$amount" } }
          }
        }
      ],
      "regionSales": [
        { $group: { _id: "$region", totalSales: { $sum: "$amount" } } }
      ]
    }
  }
]);

输出

[
  {
    "priceRanges": [
      { "_id": 0, "count": 5, "total": 250 },
      { "_id": 50, "count": 8, "total": 600 },
      { "_id": 100, "count": 3, "total": 450 },
      { "_id": "200+", "count": 2, "total": 500 }
    ],
    "regionSales": [
      { "_id": "North", "totalSales": 800 },
      { "_id": "South", "totalSales": 700 }
    ]
  }
]
注意事项
  • 每个子管道独立处理原始输入文档。
  • 输出结果为嵌套文档,字段名为子管道名称。
  • 适合需要多维度统计的场景,减少多次查询。

二. 对比与适用场景

特性$bucket$facet
功能单维度范围分组多维度并行聚合
输出结构线性数组嵌套文档(多个结果集)
复杂度简单,单一分组逻辑复杂,支持多个独立子管道
性能高效,单次分组可能较高开销,因多管道并行
典型场景按价格、年龄等分区间统计同时生成分桶、分类、排序等多结果

三. 总结

  • $bucket:适合明确分桶边界的单维度统计,如销售区间、年龄段分布。
  • $facet:适用于复杂需求,需在单次查询中生成多个统计结果,如同时分析价格分布和地区销售趋势。

正确选择两者可显著提升聚合效率,并简化数据处理流程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我不是程序媛lisa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值