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