$bucket(聚合)

在本页面

  • 定义

  • 行为

定义

  • $bucket

    • version 3.4 中的新内容。

根据指定的表达式和存储区边界,将传入的文档分组,称为存储桶。

每个存储桶在输出中表示为文档。每个存储桶的文档包含一个_id字段,其 value 指定存储桶的包含下限,而count字段包含存储桶中的文档数。如果未指定output,则默认包含count字段。

$bucket仅为包含至少一个输入文档的存储桶生成输出文档。

{
  $bucket: {
      groupBy: <expression>,
      boundaries: [ <lowerbound1>, <lowerbound2>, ... ],
      default: <literal>,
      output: {
         <output1>: { <$accumulator expression> },
         ...
         <outputN>: { <$accumulator expression> }
      }
   }
}
领域类型描述
groupBy表达一个表达到 group 的文档。要指定场路径,请在字段 name 前加上美元符号$,并将其括在引号中。
除非$bucket包含default规范,否则每个输入文档必须将groupBy字段路径或表达式解析为 value,该值属于boundaries指定的范围之一。
boundariesarray基于groupBy表达式的 array 值,用于指定每个存储桶的边界。每个相邻的值对充当包含的下边界和独占的上边界。您必须至少指定两个边界。
指定的值必须是升序 order 且所有相同的类型。 exception 是指值是混合数字类型,例如:
[ 10, NumberLong(20), NumberInt(30) ]
如果值是文档,则它们必须包装在$literal operator 中。
示例
Example
[ 0, 5, 10 ]的 array 创建两个桶:
[0,5],包含下限0和独占上限5
[5,10]包含下限5和独占上限10
default文字可选的。一个文字,指定包含groupBy表达式结果不属于boundaries指定的存储区的所有文档的附加存储桶的_id
如果未指定,则每个输入文档必须将groupBy表达式解析为boundaries指定的某个存储区范围内的 value,否则操作将引发错误。
default value 必须小于最低boundaries value,或大于或等于最高boundaries value。
default value 可以与boundaries中的条目不同类型。
output文献可选的。除字段外还指定要包括在输出文档中的字段的文档。要指定要包括的字段,必须使用累加器表达式。
<outputfield1>:{<accumulator>:<expression1>},
...
<outputfieldN>:{<accumulator>:<expressionN>}
指定output时,输出文档中不包含默认的count字段。显式指定count表达式作为输出文档的一部分以包含它:
输出:{
<outputField1>:{<accumulator>:<expression1>},
...
“count”:{$sum:1}
}

行为

$bucket要求至少满足以下条件之一或操作引发错误:

  • 每个输入文档将groupBy表达式解析为boundaries或其中指定的某个存储区范围内的 value

  • default value 被指定用于存储其groupBy值在boundaries之外或与boundaries中的值不同BSON 类型的文档。

如果groupBy表达式解析为 array 或文档,则$bucket使用$sort中的比较逻辑将输入文档排列到存储桶中。

考虑一个带有以下文档的集合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聚合阶段根据priceartwork集合排列到存储桶中:

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阶段内用于在单个聚合阶段处理多个聚合管道。

以下操作基于priceyearartwork中的文档分组到存储桶中:

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对输入文档进行分组。存储桶具有以下边界:

  • [0,200]包含下限0和独占上限200

  • [200,400]包含下限200和独占上限400

  • “其他”,包含没有价格或价格超出上述范围的文件的default桶。

第二个方面按year对输入文档进行分组。存储桶具有以下边界:

  • [1890,1910]包含下限1890和独占上限1910

  • [1910,1920],包含下限1910和独占上限1920

  • [1920,1940]包含下限1910和独占上限1940

  • “未知”,包含没有年数或年数超出上述范围的文件的default桶。

该操作返回以下文档:

{
  "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