Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ / /

$bucket (agregação)

Nesta página

  • Definição
  • Considerações
  • Sintaxe
  • Comportamento
  • Exemplos
$bucket

Novidade na versão 3.4.

Categoriza documentos de entrada em grupos, chamados buckets, com base em uma expressão especificada e limites de bucket e gera um documento por cada bucket. Cada documento de saída contém um campo _id cujo valor especifica o limite inferior inclusivo do bloco. A opção saída especifica os campos incluídos em cada documento de saída.

$bucket produz somente documentos de saída para buckets que contenham pelo menos um documento de entrada.

O estágio $bucket tem um limite de 100 megabytes de RAM. Por padrão, se o estágio exceder este limite, $bucket retornará um erro. Para permitir mais espaço para o processamento do estágio, use a opção allowDiskUse para permitir que os estágios do pipeline de agregação gravem dados em arquivos temporários.

Dica

Veja também:

{
$bucket: {
groupBy: <expression>,
boundaries: [ <lowerbound1>, <lowerbound2>, ... ],
default: <literal>,
output: {
<output1>: { <$accumulator expression> },
...
<outputN>: { <$accumulator expression> }
}
}
}

O documento $bucket contém os seguintes campos:

Campo
Tipo
Descrição
expressão

Uma expressão pela qual agrupar documentos. Para especificar um caminho do campo, prefixe o nome do campo com um sinal de dólar $ e coloque-o entre aspas.

A menos que $bucket inclua uma especificação padrão, cada documento de entrada precisa mapear o caminho do campo ou a expressão groupBy para um valor dentro dos intervalos definidos pelos limites.

array

Uma array de valores com base na expressão groupBy que especifica os limites de cada bucket. Cada par adjacente de valores atua como o limite inferior inclusivo e o limite superior exclusivo para o bucket. Você deve especificar pelo menos dois limites.

Os valores especificados devem estar em ordem crescente e todos do mesmo tipo. Exceto quando os valores são tipos numéricos mistos, como:

[ 10, NumberLong(20), NumberInt(30) ]

Por exemplo, uma array de [ 0, 5, 10 ] cria dois buckets:

  • [0, 5) com limite inferior inclusivo 0 e limite superior exclusivo 5.

  • [5, 10) com limite inferior inclusivo 5 e limite superior exclusivo 10.

literal

Opcional. Um literal que especifica o _id de um bucket adicional que contém todos os documentos cujo resultado da expressão groupBy não se enquadra em um bucket especificado por limites.

Se não for especificado, cada documento de entrada deverá resolver a expressão groupBy para um valor dentro de um dos intervalos de bucket especificados por boundaries ou a operação gerará um erro.

O valor default deve ser menor que o valor boundaries mais baixo ou maior ou igual ao valor boundaries mais alto.

O valor default pode ser de um tipo diferente das entradas em boundaries.

documento

Opcional. Um documento que especifica os campos a serem incluídos nos documentos de saída, além do campo _id. Para especificar o campo a incluir, você deve usar acumulador de expressões.

<outputfield1>: { <accumulator>: <expression1> },
...
<outputfieldN>: { <accumulator>: <expressionN> }

Se você não especificar um documento de output, a operação retornará um campo count que contém o número de documentos em cada bucket.

Se você especificar um documento de output, somente os campos especificados no documento serão retornados; ou seja, o campo count não será retornado a menos que seja explicitamente incluído no documento de output.

$bucket requer que pelo menos uma das seguintes condições seja atendida ou que a operação apresente um erro:

  • Cada documento de entrada resolve a expressão groupBy para um valor dentro de um dos intervalos de bucket especificados por limites ou

  • Um valor padrão é especificado para armazenar os documentos cujos valores groupBy estão fora dos boundaries ou de um tipo de BSON diferente dos valores em boundaries.

Se a expressão groupBy for resolvida para uma array ou um documento, $bucket organizará os documentos de entrada em buckets utilizando a lógica de comparação de $sort.

No mongosh, crie uma coleção de amostra denominada artists com os seguintes documentos:

db.artists.insertMany([
{ "_id" : 1, "last_name" : "Bernard", "first_name" : "Emil", "year_born" : 1868, "year_died" : 1941, "nationality" : "France" },
{ "_id" : 2, "last_name" : "Rippl-Ronai", "first_name" : "Joszef", "year_born" : 1861, "year_died" : 1927, "nationality" : "Hungary" },
{ "_id" : 3, "last_name" : "Ostroumova", "first_name" : "Anna", "year_born" : 1871, "year_died" : 1955, "nationality" : "Russia" },
{ "_id" : 4, "last_name" : "Van Gogh", "first_name" : "Vincent", "year_born" : 1853, "year_died" : 1890, "nationality" : "Holland" },
{ "_id" : 5, "last_name" : "Maurer", "first_name" : "Alfred", "year_born" : 1868, "year_died" : 1932, "nationality" : "USA" },
{ "_id" : 6, "last_name" : "Munch", "first_name" : "Edvard", "year_born" : 1863, "year_died" : 1944, "nationality" : "Norway" },
{ "_id" : 7, "last_name" : "Redon", "first_name" : "Odilon", "year_born" : 1840, "year_died" : 1916, "nationality" : "France" },
{ "_id" : 8, "last_name" : "Diriks", "first_name" : "Edvard", "year_born" : 1855, "year_died" : 1930, "nationality" : "Norway" }
])

A operação a seguir agrupa os documentos em buckets de acordo com o campo year_born e filtra com base na contagem de documentos nos buckets:

db.artists.aggregate( [
// First Stage
{
$bucket: {
groupBy: "$year_born", // Field to group by
boundaries: [ 1840, 1850, 1860, 1870, 1880 ], // Boundaries for the buckets
default: "Other", // Bucket ID for documents which do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 },
"artists" :
{
$push: {
"name": { $concat: [ "$first_name", " ", "$last_name"] },
"year_born": "$year_born"
}
}
}
}
},
// Second Stage
{
$match: { count: {$gt: 3} }
}
] )
Primeira etapa

A etapa $bucket agrupa os documentos em buckets pelo campo year_born. Os blocos têm os seguintes limites:

  • [1840, 1850) com limite inferior inclusivo de 1840 e limite superior exclusivo de 1850.

  • [1850, 1860) com limite inferior inclusivo 1850 e limite superior exclusivo 1860.

  • [1860, 1870) com limite inferior inclusivo 1860 e limite superior exclusivo 1870.

  • [1870, 1880) com limite inferior inclusivo 1870 e limite superior exclusivo 1880.

  • Se um documento não contivesse o campo year_born ou seu campo year_born estivesse fora dos intervalos acima, ele seria colocado no bucket padrão com o valor _id "Other".

O estágio inclui o documento de saída para determinar os campos a serem retornados:

Campo
Descrição
_id
Limite inferior inclusivo do bucket.
count
Contagem de documentos no bucket.
artists

Array de documentos contendo informações sobre cada artista no bucket. Cada documento contém o seguinte sobre o artista:

  • name, que é uma concatenação (ou seja, $concat) do first_name e last_name do artista.

  • year_born

Este estágio passa os seguintes documentos para o próximo estágio:

{ "_id" : 1840, "count" : 1, "artists" : [ { "name" : "Odilon Redon", "year_born" : 1840 } ] }
{ "_id" : 1850, "count" : 2, "artists" : [ { "name" : "Vincent Van Gogh", "year_born" : 1853 },
{ "name" : "Edvard Diriks", "year_born" : 1855 } ] }
{ "_id" : 1860, "count" : 4, "artists" : [ { "name" : "Emil Bernard", "year_born" : 1868 },
{ "name" : "Joszef Rippl-Ronai", "year_born" : 1861 },
{ "name" : "Alfred Maurer", "year_born" : 1868 },
{ "name" : "Edvard Munch", "year_born" : 1863 } ] }
{ "_id" : 1870, "count" : 1, "artists" : [ { "name" : "Anna Ostroumova", "year_born" : 1871 } ] }
Segunda etapa

O estágio $match filtra a saída do estágio anterior para retornar apenas buckets que contenham mais de três documentos.

A operação retorna o seguinte documento:

{ "_id" : 1860, "count" : 4, "artists" :
[
{ "name" : "Emil Bernard", "year_born" : 1868 },
{ "name" : "Joszef Rippl-Ronai", "year_born" : 1861 },
{ "name" : "Alfred Maurer", "year_born" : 1868 },
{ "name" : "Edvard Munch", "year_born" : 1863 }
]
}

Você pode usar o estágio $facet para executar várias agregações $bucket em um único estágio.

No mongosh, crie uma coleção de amostra denominada artwork com os seguintes documentos:

db.artwork.insertMany([
{ "_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") }
])

A operação a seguir usa dois estágios $bucket dentro de um estágio $facet para criar dois agrupamentos, um por price e outro por year:

db.artwork.aggregate( [
{
$facet: { // Top-level $facet stage
"price": [ // Output field 1
{
$bucket: {
groupBy: "$price", // Field to group by
boundaries: [ 0, 200, 400 ], // Boundaries for the buckets
default: "Other", // Bucket ID for documents which do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 },
"artwork" : { $push: { "title": "$title", "price": "$price" } },
"averagePrice": { $avg: "$price" }
}
}
}
],
"year": [ // Output field 2
{
$bucket: {
groupBy: "$year", // Field to group by
boundaries: [ 1890, 1910, 1920, 1940 ], // Boundaries for the buckets
default: "Unknown", // Bucket ID for documents which do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 },
"artwork": { $push: { "title": "$title", "year": "$year" } }
}
}
}
]
}
}
] )
Primeira faceta

A primeira faceta agrupa os documentos de entrada por price. Os buckets têm os seguintes limites:

  • [0, 200) com limite inferior inclusivo 0 e limite superior exclusivo 200.

  • [200, 400) com limite inferior inclusivo 200 e limite superior exclusivo 400.

  • "Other", o bucket default que contém documentos sem preços ou preços fora das faixas acima.

O estágio $bucket inclui o documento de saída para determinar os campos a serem retornados:

Campo
Descrição
_id
Limite inferior inclusivo do bucket.
count
Contagem de documentos no bucket.
artwork
Array de documentos contendo informações sobre cada obra de arte no bucket.
averagePrice
Emprega o operador $avg para exibir o preço médio de todas as obras de arte no bucket.
Segunda faceta

A segunda faceta agrupa os documentos de entrada por year. Os buckets têm os seguintes limites:

  • [1890, 1910) com limite inferior inclusivo de 1890 e limite superior exclusivo de 1910.

  • [1910, 1920) com limite inferior inclusivo de 1910 e limite superior exclusivo de 1920.

  • [1920, 1940) com limite inferior inclusivo de 1910 e limite superior exclusivo de 1940.

  • " Unknown ", o bucket default contendo documentos sem anos ou anos fora dos intervalos acima.

O estágio $bucket inclui o documento de saída para determinar os campos a serem retornados:

Campo
Descrição
count
Contagem de documentos no bucket.
artwork
Array de documentos contendo informações sobre cada obra de arte no bucket.
Saída

A operação retorna o seguinte documento:

{
"price" : [ // Output of first facet
{
"_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") }
],
"averagePrice" : NumberDecimal("140.4375")
},
{
"_id" : 200,
"count" : 2,
"artwork" : [
{ "title" : "Melancholy III", "price" : NumberDecimal("280.00") },
{ "title" : "Composition VII", "price" : NumberDecimal("385.00") }
],
"averagePrice" : NumberDecimal("332.50")
},
{
// Includes documents without prices and prices greater than 400
"_id" : "Other",
"count" : 2,
"artwork" : [
{ "title" : "The Persistence of Memory", "price" : NumberDecimal("483.00") },
{ "title" : "The Scream" }
],
"averagePrice" : NumberDecimal("483.00")
}
],
"year" : [ // Output of second facet
{
"_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 documents without a year
"_id" : "Unknown",
"count" : 1,
"artwork" : [
{ "title" : "The Great Wave off Kanagawa" }
]
}
]
}

Dica

Veja também:

Voltar

$addFields