On this page
$bucket (aggregation)
在本页面
Definition
- $bucket- 3.4 版的新功能。
 
根据指定的表达式和存储段边界将传入文档分类为称为存储段的组。
每个存储段在输出中均表示为文档。每个存储桶的文档包含一个_id字段,其值指定存储桶的包含下限;一个count字段包含该存储桶中的文档数。未指定output时,默认情况下包括count字段。
$bucket仅为包含至少一个 Importing 文档的存储桶生成输出文档。
{
  $bucket: {
      groupBy: <expression>,
      boundaries: [ <lowerbound1>, <lowerbound2>, ... ],
      default: <literal>,
      output: {
         <output1>: { <$accumulator expression> },
         ...
         <outputN>: { <$accumulator expression> }
      }
   }
}
| Field | Type | Description | 
|---|---|---|
| groupBy | expression | expression用于分组文档。要指定field path,请在字段名前加上美元符号 $并将其括在引号中。 | 
除非$bucket包含default规范,否则每个 Importing 文档都必须将groupBy字段路径或表达式解析为落入boundaries指定的范围之一内的值。
| boundaries | array |基于groupBy表达式的值数组,这些值指定每个存储区的边界。每个相邻的值对都充当存储桶的包含下边界和专有上边界。您必须至少指定两个边界。
指定的值必须按升序排列,并且所有值都相同type。exception 是值是混合数字类型,例如:[ 10, NumberLong(20), NumberInt(30) ]
如果值为文档,则必须将它们包装在$literal运算符中。
Example
[ 0, 5, 10 ]数组创建两个存储桶:
[0,5)的下限为0,上限为5。
> [5,10)的下限为5,上限为10。
|
| default |Literals|可选。一个 Literals,它指定另一个存储桶的_id,该存储桶包含所有groupBy表达式结果不属于boundaries指定的存储桶的文档。
> 如果未指定,则每个 Importing 文档必须将groupBy表达式解析为boundaries指定的存储区范围之一内的值,否则该操作将引发错误。
> default值必须小于最低boundaries值,或大于或等于最高boundaries值。
> default的值可以不同于boundaries中的条目的type。
| output |文档|可选。一个文档,除了_id字段外,它还指定要包含在输出文档中的字段。要指定要包括的字段,您必须使用accumulator expressions。
> <outputfield1>: { <accumulator>: <expression1> },
> ...
> <outputfieldN>: { <accumulator>: <expressionN> }
> 指定output时,默认的count字段不包括在输出文档中。明确指定count表达式作为输出文档的一部分以包含它:
> output: {
> <outputField1>: { <accumulator>: <expression1> },
> ...
> "count": { $sum: 1 }
> }|
Behavior
$bucket至少满足以下条件之一,否则操作会引发错误:
- 每个 Importing 文档将 - groupBy表达式解析为- boundaries指定的存储区范围之一内的值,或者
- 为 - groupBy值在- boundaries之外或与- boundaries中的值不同的BSON type的存储桶文档指定- default值。
如果groupBy表达式解析为数组或文档,则$bucket使用$sort的比较逻辑将 Importing 文档排列到存储桶中。
Example
考虑包含以下文档的集合artwork:
{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
    "price" : NumberDecimal("199.99") }
{ "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
    "price" : NumberDecimal("280.00") }
{ "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
    "price" : NumberDecimal("76.04") }
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
    "price" : NumberDecimal("167.30") }
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
    "price" : NumberDecimal("483.00") }
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
    "price" : NumberDecimal("385.00") }
{ "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893
    /* No price*/ }
{ "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,
    "price" : NumberDecimal("118.42") }
以下操作使用$bucket聚合阶段,根据price将artwork集合安排到存储桶中:
db.artwork.aggregate( [
  {
    $bucket: {
      groupBy: "$price",
      boundaries: [ 0, 200, 400 ],
      default: "Other",
      output: {
        "count": { $sum: 1 },
        "titles" : { $push: "$title" }
      }
    }
  }
] )
这些存储桶具有以下边界:
- [0,200)包含下限 - 0和上限- 200。
- [200,400)包含下限 - 200和上限- 400。
- “其他”是不含价格或价格不在上述范围内的文档的 - default存储桶。
该操作返回以下文档:
{
  "_id" : 0,
  "count" : 4,
  "titles" : [
    "The Pillars of Society",
    "Dancer",
    "The Great Wave off Kanagawa",
    "Blue Flower"
  ]
}
{
  "_id" : 200,
  "count" : 2,
  "titles" : [
    "Melancholy III",
    "Composition VII"
  ]
}
{
  "_id" : "Other",
  "count" : 2,
  "titles" : [
    "The Persistence of Memory",
    "The Scream"
  ]
}
将$ bucket 与$ facet 结合使用
$bucket阶段可用于$facet阶段,以在单个聚合阶段中处理artwork上的多个聚合管道。
以下操作基于artwork和year将artwork中的文档分组到存储桶中:
db.artwork.aggregate( [
  {
    $facet: {
      "price": [
        {
          $bucket: {
              groupBy: "$price",
              boundaries: [ 0, 200, 400 ],
              default: "Other",
              output: {
                "count": { $sum: 1 },
                "artwork" : { $push: { "title": "$title", "price": "$price" } }
              }
          }
        }
      ],
      "year": [
        {
          $bucket: {
            groupBy: "$year",
            boundaries: [ 1890, 1910, 1920, 1940 ],
            default: "Unknown",
            output: {
              "count": { $sum: 1 },
              "artwork": { $push: { "title": "$title", "year": "$year" } }
            }
          }
        }
      ]
    }
  }
] )
第一个方面按price将 Importing 文档分组。这些存储桶具有以下边界:
- [0,200)包含下限 - 0和上限- 200。
- [200,400)包含下限 - 200和上限- 400。
- “其他”,是包含文档的“默认”存储桶,其中没有价格或价格不在上述范围内。 
第二个方面按year将 Importing 文档分组。这些存储桶具有以下边界:
- [1890,1910)包含下限 - 1890和上限- 1910。
- [1910,1920)包含下限 - 1910和上限- 1920。
- [1920,1940)包含下限 - 1910和上限- 1940。
- “未知”,是“默认”存储桶,其中包含没有超出上述范围的年份或年份的文档。 
该操作返回以下文档:
{
  "year" : [
    {
      "_id" : 1890,
      "count" : 2,
      "artwork" : [
        {
          "title" : "Melancholy III",
          "year" : 1902
        },
        {
          "title" : "The Scream",
          "year" : 1893
        }
      ]
    },
    {
      "_id" : 1910,
      "count" : 2,
      "artwork" : [
        {
          "title" : "Composition VII",
          "year" : 1913
        },
        {
          "title" : "Blue Flower",
          "year" : 1918
        }
      ]
    },
    {
      "_id" : 1920,
      "count" : 3,
      "artwork" : [
        {
          "title" : "The Pillars of Society",
          "year" : 1926
        },
        {
          "title" : "Dancer",
          "year" : 1925
        },
        {
          "title" : "The Persistence of Memory",
          "year" : 1931
        }
      ]
    },
    {
      // Includes the document without a year, e.g., _id: 4
      "_id" : "Unknown",
      "count" : 1,
      "artwork" : [
        {
          "title" : "The Great Wave off Kanagawa"
        }
      ]
    }
  ],
      "price" : [
    {
      "_id" : 0,
      "count" : 4,
      "artwork" : [
        {
          "title" : "The Pillars of Society",
          "price" : NumberDecimal("199.99")
        },
        {
          "title" : "Dancer",
          "price" : NumberDecimal("76.04")
        },
        {
          "title" : "The Great Wave off Kanagawa",
          "price" : NumberDecimal("167.30")
        },
        {
          "title" : "Blue Flower",
          "price" : NumberDecimal("118.42")
        }
      ]
    },
    {
      "_id" : 200,
      "count" : 2,
      "artwork" : [
        {
          "title" : "Melancholy III",
          "price" : NumberDecimal("280.00")
        },
        {
          "title" : "Composition VII",
          "price" : NumberDecimal("385.00")
        }
      ]
    },
    {
      // Includes the document without a price, e.g., _id: 7
      "_id" : "Other",
      "count" : 2,
      "artwork" : [
        {
          "title" : "The Persistence of Memory",
          "price" : NumberDecimal("483.00")
        },
        {
          "title" : "The Scream"
        }
      ]
    }
  ]
}
另请参见$bucketAuto