$bucketAuto(聚合)

在本页面

定义

  • $bucketAuto

    • version 3.4 中的新内容。

根据指定的表达式将传入的文档分类为特定数量的组(称为存储桶)。自动确定存储桶边界,以尝试将文档均匀地分配到指定数量的存储桶中。

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

$bucketAuto阶段具有以下形式:

{
  $bucketAuto: {
      groupBy: <expression>,
      buckets: <number>,
      output: {
         <output1>: { <$accumulator expression> },
         ...
      }
      granularity: <string>
  }
}
领域类型描述
groupBy表达一个表达到 group 的文档。要指定场路径,请在字段 name 前加上美元符号$,并将其括在引号中。
buckets整数正 32-bit integer,指定输入文档分组到的存储区数。
output文献可选的。除字段外还指定要包括在输出文档中的字段的文档。要指定要包括的字段,必须使用累加器表达式
<outputfield1>:{<accumulator>:<expression1>},
...
当指定output时,输出文档中不包含默认的count字段。明确指定count表达式作为output文档的一部分以包含它:
输出:{
<outputfield1>:{<accumulator>:<expression1>},
...
count:{$sum:1}
}
granularity可选的。一个 string,指定首选号码系列用于确保计算的边界边缘以首选 round numbers 结束或它们的权力为 10.
仅当所有groupBy值都是数字且 none 只有NaN时才可用。
支持的granularity值为:
"R5"
"R10"

行为

如果出现以下情况,可能会少于指定数量的存储桶:

  • 输入文档的数量小于指定的存储桶数量。

  • groupBy表达式的唯一值的数量小于指定的buckets的数量。

  • granularity的间隔比buckets的数量少。

  • granularity不够精确,无法将文档均匀分布到指定数量的buckets中。

如果groupBy表达式引用 array 或文档,则在确定存储区边界之前,使用与$sort中相同的 ordering 排列值。

跨桶的均匀分布取决于groupBy字段的基数或唯一值的数量。如果基数不够高,则$bucketAuto 阶段可能无法在桶之间均匀分布结果。

粒度

$bucketAuto接受一个可选的granularity参数,该参数确保所有存储桶的边界都符合指定的首选号码系列。使用首选数字系列可以更好地控制在groupBy表达式中的值范围中设置存储区边界的位置。当groupBy表达式的范围呈指数级变化时,它们还可用于以对数方式帮助并均匀地设置桶边界。

雷纳系列

Renard 数字系列是通过取 10 的第 5,第 10,第 20,第 40 或第 80 根得到的 numbers 的集合,然后包括等于 1.0 到 10.0 之间的值的各种权力(10.3 in R80的情况。

granularity设置为R5R10R20R40R80可将存储区边界限制为系列中的值。当groupBy值超出 1.0 至 10.0(10.3 为R80)范围时,系列的值乘以 10 的幂。

  • 10 0/5 = 1

  • 10 1/5 = 1.584 ~ 1.6

  • 10 2/5 = 2.511 ~ 2.5

  • 10 3/5 = 3.981 ~ 4.0

  • 10 4/5 = 6.309 ~ 6.3

  • 10 5/5 = 10

同样的方法应用于其他 Renard 系列,以提供更精细的粒度 i.e。,1.0 和 10.0 之间的间隔更多(10.3 为R80)。

E 系列

E 数系列与雷纳系列类似,因为它们将具有特定相对误差的第 6,第 12,第 24,第 48,第 96 或第 192 根的区间从 1.0 细分为 10.0.

granularity设置为E6E12E24E48E96E192以将存储区边界限制为系列中的值。当groupBy值超出 1.0 至 10.0 范围时,系列的值乘以 10 的幂。要了解有关 E-series 及其各自相对错误的更多信息,请参阅首选号码系列

1-2-5 系列

如果存在这样的系列,则1-2-5系列的行为类似于 three-value 雷纳系列

granularity设置为1-2-5以将铲斗边界限制为 10 的第三个根的各种幂,舍入为一个有效数字。

以下值是1-2-5系列的一部分:0.1,0.2,0.5,1,2,5,10,20,50,100,200,500,1000 等等......

两个系列的力量

granularity设置为POWERSOF2以将存储区边界限制为 numbers,它是 2 的幂。

1,2,4,8,16,32,64,128,256,512,1024,2048 等等.......

比较不同的粒度

以下操作演示了如何为granularity指定不同的值会影响$bucketAuto如何确定存储区边界。 things的集合_id编号从 1 到 100:

{ _id: 1 }
{ _id: 2 }
...
{ _id: 100 }

granularity的不同值将替换为以下操作:

db.things.aggregate( [
  {
    $bucketAuto: {
      groupBy: "$_id",
      buckets: 5,
      granularity: <granularity>
    }
  }
] )

以下 table 中的结果演示了granularity yield 不同存储区边界的不同值:

粒度结果笔记
没有粒度{“_id”:{“min”:0,“max”:20},“count”:20}
{“_id”:{“min”:20,“max”:40} ,“count”:20}
{“_id”:{“min”:40,“max”:60},“count”:20}
{“_id”:{“min “:60,”max“:80},”count“:20}
{”_id“:{”min“:80,”max“:99},”count“:20}
**** R20{“_id”:{“min”:0,“max”:20},“count”:20}
{“_id”:{“min”:20,“max”:40} ,“count”:20}
{“_id”:{“min”:40,“max”:63},“count”:23}
{“_id”:{“min “:63,”max“:90},”count“:27}
{”_id“:{”min“:90,”max“:100},”count“:10}
E24{“_id”:{“min”:0,“max”:20},“count”:20}
{“_id”:{“min”:20,“max”:43} ,“count”:23}
{“_id”:{“min”:43,“max”:68},“count”:25}
{“_id”:{“min “:68,”max“:91},”count“:23}
{”_id“:{”min“:91,”max“:100},”count“:9}
1-2-5{“_id”:{“min”:0,“max”:20},“count”:20}
{“_id”:{“min”:20,“max”:50} ,“count”:30}
{“_id”:{“min”:50,“max”:100},“count”:50}
指定数量的存储桶超过了系列中的间隔数。
**** POWERSOF2{“_id”:{“min”:0,“max”:32},“count”:32}
{“_id”:{“min”:32,“max”:64} ,“count”:32}
{“_id”:{“min”:64,“max”:128},“count”:36}
指定数量的存储桶超过了系列中的间隔数。

考虑一个带有以下文档的集合artwork

{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
    "price" : NumberDecimal("199.99"),
    "dimensions" : { "height" : 39, "width" : 21, "units" : "in" } }
{ "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
    "price" : NumberDecimal("280.00"),
    "dimensions" : { "height" : 49, "width" : 32, "units" : "in" } }
{ "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
    "price" : NumberDecimal("76.04"),
    "dimensions" : { "height" : 25, "width" : 20, "units" : "in" } }
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
    "price" : NumberDecimal("167.30"),
    "dimensions" : { "height" : 24, "width" : 36, "units" : "in" } }
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
    "price" : NumberDecimal("483.00"),
    "dimensions" : { "height" : 20, "width" : 24, "units" : "in" } }
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
    "price" : NumberDecimal("385.00"),
    "dimensions" : { "height" : 30, "width" : 46, "units" : "in" } }
{ "_id" : 7, "title" : "The Scream", "artist" : "Munch",
    "price" : NumberDecimal("159.00"),
    "dimensions" : { "height" : 24, "width" : 18, "units" : "in" } }
{ "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,
    "price" : NumberDecimal("118.42"),
    "dimensions" : { "height" : 24, "width" : 20, "units" : "in" } }

单面聚合

在以下操作中,根据price字段中的值将输入文档分组为四个存储桶:

db.artwork.aggregate( [
   {
     $bucketAuto: {
         groupBy: "$price",
         buckets: 4
     }
   }
] )

该操作返回以下文档:

{
  "_id" : {
    "min" : NumberDecimal("76.04"),
    "max" : NumberDecimal("159.00")
  },
  "count" : 2
}
{
  "_id" : {
    "min" : NumberDecimal("159.00"),
    "max" : NumberDecimal("199.99")
  },
  "count" : 2
}
{
  "_id" : {
    "min" : NumberDecimal("199.99"),
    "max" : NumberDecimal("385.00")
  },
  "count" : 2
}
{
  "_id" : {
    "min" : NumberDecimal("385.00"),
    "max" : NumberDecimal("483.00")
  },
  "count" : 2
}

Multi-Faceted 聚合

可以在$facet阶段中使用$bucketAuto阶段来处理来自artwork的同一组输入文档上的多个聚合管道。

以下聚合管道根据priceyear和计算的areaartwork集合中的文档分组到存储桶中:

db.artwork.aggregate( [
  {
    $facet: {
      "price": [
        {
          $bucketAuto: {
            groupBy: "$price",
            buckets: 4
          }
        }
      ],
      "year": [
        {
          $bucketAuto: {
            groupBy: "$year",
            buckets: 3,
            output: {
              "count": { $sum: 1 },
              "years": { $push: "$year" }
            }
          }
        }
      ],
      "area": [
        {
          $bucketAuto: {
            groupBy: {
              $multiply: [ "$dimensions.height", "$dimensions.width" ]
            },
            buckets: 4,
            output: {
              "count": { $sum: 1 },
              "titles": { $push: "$title" }
            }
          }
        }
      ]
    }
  }
] )

该操作返回以下文档:

{
  "area" : [
    {
      "_id" : { "min" : 432, "max" : 500 },
      "count" : 3,
      "titles" : [
        "The Scream",
        "The Persistence of Memory",
        "Blue Flower"
      ]
    },
    {
      "_id" : { "min" : 500, "max" : 864 },
      "count" : 2,
      "titles" : [
        "Dancer",
        "The Pillars of Society"
      ]
    },
    {
      "_id" : { "min" : 864, "max" : 1568 },
      "count" : 2,
      "titles" : [
        "The Great Wave off Kanagawa",
        "Composition VII"
      ]
    },
    {
      "_id" : { "min" : 1568, "max" : 1568 },
      "count" : 1,
      "titles" : [
        "Melancholy III"
      ]
    }
  ],
  "price" : [
    {
      "_id" : { "min" : NumberDecimal("76.04"), "max" : NumberDecimal("159.00") },
      "count" : 2
    },
    {
      "_id" : { "min" : NumberDecimal("159.00"), "max" : NumberDecimal("199.99") },
      "count" : 2
    },
    {
      "_id" : { "min" : NumberDecimal("199.99"), "max" : NumberDecimal("385.00") },
      "count" : 2 },
    {
      "_id" : { "min" : NumberDecimal("385.00"), "max" : NumberDecimal("483.00") },
      "count" : 2
    }
  ],
  "year" : [
    { "_id" : { "min" : null, "max" : 1913 }, "count" : 3, "years" : [ 1902 ] },
    { "_id" : { "min" : 1913, "max" : 1926 }, "count" : 3, "years" : [ 1913, 1918, 1925 ] },
    { "_id" : { "min" : 1926, "max" : 1931 }, "count" : 2, "years" : [ 1926, 1931 ] }
  ]
}