Definição
$bucketAutoCategoriza documentos recebidos em um número específico de grupos, chamados blocos, com base em uma expressão especificada. Os limites dos compartimentos são determinados automaticamente em uma tentativa de distribuir uniformemente os documentos no número especificado de compartimentos.
Cada bucket é representado como um documento na saída. O documento para cada bucket contém:
Um objeto
_idque especifica os limites do bucket.O campo
_id.minespecifica o limite inferior inclusivo para o bucket.O campo
_id.maxespecifica o limite superior para o bucket. Esse limite é exclusivo para todos os buckets, exceto para o bucket final da série, onde é inclusivo.
Um campo
countque contém o número de documentos no bucket. O campocounté incluído por padrão quando o documentooutputnão é especificado.
O estágio
$bucketAutotem a seguinte forma:{ $bucketAuto: { groupBy: <expression>, buckets: <number>, output: { <output1>: { <$accumulator expression> }, ... } granularity: <string> } } CampoTipoDescriçãogroupByexpressão
Umaexpressão pela qual agrupar documentos. Para especificar um caminho do campo, prefixe o nome do campo com um cifrão
$e coloque-o entre aspas.bucketsinteiro
Um número inteiro positivo de 32 bits que especifica o número de buckets nos quais os documentos de entrada são agrupados.
outputdocumento
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 ser incluído, você deve usar expressões accumulator:<outputfield1>: { <accumulator>: <expression1> }, ... O campo
countpadrão não é incluído no documento de saída quandooutputé especificado. Especifique explicitamente a expressãocountcomo parte do documentooutputpara incluí-la:output: { <outputfield1>: { <accumulator>: <expression1> }, ... count: { $sum: 1 } } granularitystring
Opcional. Uma string que especifica a série numérica preferencial a ser usada para garantir que as bordas do limite calculado terminem em números redondos preferenciais ou em suas potências de 10.
Disponível somente se todos os valores de
groupByforem numéricos e nenhum deles forNaN.Os valores suportados de
granularitysão:"R5""R10""R20""R40""R80""1-2-5"
"E6""E12""E24""E48""E96""E192""POWERSOF2"
Considerações
$bucketAuto e restrições de memória
O estágio $bucketAuto tem um limite de 100 megabytes de RAM. Por padrão, se o estágio exceder esse limite, o MongoDB gravará automaticamente arquivos temporários em disco. Para detalhes, consulte allowDiskUseByDefault.
Comportamento
Pode haver menos do que o número especificado de buckets se:
O número de documentos de entrada é menor que o número especificado de buckets.
O número de valores únicos da expressão
groupByé menor que o número especificado debuckets.O
granularitytem menos intervalos do que o número debuckets.O
granularitynão é suficiente para distribuir uniformemente os documentos no número especificado debuckets.
Se a expressão groupBy se referir a uma array ou documento, os valores serão organizados usando a mesma ordem de $sort antes de determinar os buckets do intervalo.
A distribuição uniforme de documentos entre buckets depende da cardinalidade, ou do número de valores únicos, do campo groupBy. Se a cardinalidade não for alta o suficiente, o estágio $bucketAuto pode não distribuir uniformemente os resultados entre os buckets.
Granularidade
O $bucketAuto aceita um granularity parâmetro opcional que garante que os limites de todos os buckets sigam uma série de números preferenciais especificada. O uso de uma série numérica preferencial fornece mais controle sobre onde os limites do bucket são definidos entre o intervalo de valores na expressão groupBy . Eles também podem ser usados para ajudar a definir logaritmicamente e uniformemente os limites do bucket quando o intervalo da expressão groupBy escala exponencialmente.
Série Renard
As séries de números de Renard são conjuntos de números derivados da 5ª, 10ª ,20ª , 40ª ou 80ª raiz de 10 e, em seguida, incluindo várias potências da raiz que equivalem a valores entre 1,0 a 10,0 (10,3 no caso de R80).
Configure granularity para R5, R10, R20, R40 ou R80 para restringir os limites do bucket para valores na série. Os valores da série são multiplicados por uma potência de 10 quando os valores de groupBy estão fora do intervalo de 1,0 a 10,0 (10,3 para R80).
Exemplo
A série R5 é baseada na quinta raiz de 10, que é 1,58, e inclui várias potências dessa raiz (arredondada) até que 10 seja atingida. A série R5 é derivada da seguinte forma:
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
A mesma abordagem é aplicada à outra série Renard para oferecer granularidade mais fina, ou seja, mais intervalos entre 1,0 e 10,0 (10,3 para R80).
Série E
A série de números E é semelhante à série Renard, pois subdivide o intervalo de 1.0 a 10.0 por 6 , 12 , 24 , 48 , 96 }, ou 192 nd raiz de dez com um erro relativo específico.
Configure granularity para E6, E12, E24, E48, E96 ou E192 para restringir os limites de buckets para valores na série. Os valores da série são multiplicados por uma potência de 10 quando os valores de groupBy estão fora do intervalo de 1.0 a 10.0. Para saber mais sobre a série E e seus respectivos erros relativos, consulte série de números preferenciais.
Série 1-2-5
A série 1-2-5 se comporta como uma série Renard de três valores, se essa série existisse.
Defina granularity para 1-2-5 para restringir os limites do bucket a vários poderes da terceira raiz de 10, arredondada para um dígito significativo.
Exemplo
Os seguintes valores são parte da série 1-2-5: 0,1, 0,2, 0,5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000 e assim por diante...
Poderes de Duas Séries
Defina granularity como POWERSOF2 para restringir os limites do bucket a números que são uma potência de dois.
Exemplo
Os números a seguir estão de acordo com a potência de duas séries:
2 0 = 1
2 1 = 2
2 2 = 4
2 3 = 8
2 4 = 16
2 5 = 32
e assim por diante...
Uma implementação comum é como vários componentes do computador, como memória, geralmente aderem ao definir POWERSOF2 de números preferenciais:
1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, and so on....
Comparação de diferentes granularidades
A operação a seguir demonstra como a especificação de valores diferentes para granularity afeta o modo como $bucketAuto determina os limites do bucket. Uma coleção de things tem um _id numerado de 0 a 99:
{ _id: 0 } { _id: 1 } ... { _id: 99 }
Valores diferentes para granularity são substituídos na seguinte operação:
db.things.aggregate( [ { $bucketAuto: { groupBy: "$_id", buckets: 5, granularity: <granularity> } } ] )
Os resultados na tabela a seguir demonstram como valores diferentes para granularity geram limites de bucket diferentes:
Granularidade | Resultados | Notas |
|---|---|---|
Sem granularidade | { "_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 } | O número especificado de buckets excede o número de faixas na série. |
POTÊNCIAS DE 2 | { "_id" : { "min" : 0, "max" : 32 }, "count" : 32 } { "_id" : { "min" : 32, "max" : 64 }, "count" : 32 } { "_id" : { "min" : 64, "max" : 128 }, "count" : 36 } | O número especificado de buckets excede o número de faixas na série. |
Exemplos
Considere uma coleção artwork com os seguintes documentos:
{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926, "price" : Decimal128("199.99"), "dimensions" : { "height" : 39, "width" : 21, "units" : "in" } } { "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902, "price" : Decimal128("280.00"), "dimensions" : { "height" : 49, "width" : 32, "units" : "in" } } { "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925, "price" : Decimal128("76.04"), "dimensions" : { "height" : 25, "width" : 20, "units" : "in" } } { "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai", "price" : Decimal128("167.30"), "dimensions" : { "height" : 24, "width" : 36, "units" : "in" } } { "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931, "price" : Decimal128("483.00"), "dimensions" : { "height" : 20, "width" : 24, "units" : "in" } } { "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913, "price" : Decimal128("385.00"), "dimensions" : { "height" : 30, "width" : 46, "units" : "in" } } { "_id" : 7, "title" : "The Scream", "artist" : "Munch", "price" : Decimal128("159.00"), "dimensions" : { "height" : 24, "width" : 18, "units" : "in" } } { "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918, "price" : Decimal128("118.42"), "dimensions" : { "height" : 24, "width" : 20, "units" : "in" } }
Agregação única de facet
Na seguinte operação, os documentos de entrada são agrupados em quatro blocos de acordo com os valores no campo price:
db.artwork.aggregate( [ { $bucketAuto: { groupBy: "$price", buckets: 4 } } ] )
A operação retorna os seguintes documentos:
{ "_id" : { "min" : Decimal128("76.04"), "max" : Decimal128("159.00") }, "count" : 2 } { "_id" : { "min" : Decimal128("159.00"), "max" : Decimal128("199.99") }, "count" : 2 } { "_id" : { "min" : Decimal128("199.99"), "max" : Decimal128("385.00") }, "count" : 2 } { "_id" : { "min" : Decimal128("385.00"), "max" : Decimal128("483.00") }, "count" : 2 }
Agregação múltipla de facets
O estágio $bucketAuto pode ser usado dentro do estágio $facet para processar vários aggregation pipelines no mesmo conjunto de documentos de entrada do artwork.
O aggregation pipeline a seguir agrupa os documentos da coleção artwork em buckets com base em price, year e area calculados:
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" } } } } ] } } ] )
A operação retorna o seguinte documento:
{ "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" : Decimal128("76.04"), "max" : Decimal128("159.00") }, "count" : 2 }, { "_id" : { "min" : Decimal128("159.00"), "max" : Decimal128("199.99") }, "count" : 2 }, { "_id" : { "min" : Decimal128("199.99"), "max" : Decimal128("385.00") }, "count" : 2 }, { "_id" : { "min" : Decimal128("385.00"), "max" : Decimal128("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 ] } ] }
Os exemplos de C# nesta página utilizam o banco de dados sample_mflix a partir dos conjuntos de dados de amostra do Atlas. Para saber como criar um cluster MongoDB Atlas gratuito e carregar os conjuntos de dados de exemplo, consulte Introdução na documentação do driver MongoDB .NET/C#.
A seguinte classe Movie modela os documentos na collection sample_mflix.movies:
public class Movie { public ObjectId Id { get; set; } public int Runtime { get; set; } public string Title { get; set; } public string Rated { get; set; } public List<string> Genres { get; set; } public string Plot { get; set; } public ImdbData Imdb { get; set; } public int Year { get; set; } public int Index { get; set; } public string[] Comments { get; set; } [] public DateTime LastUpdated { get; set; } }
Observação
ConventionPack para Pascal Case
As classes C# nesta página usam Pascal case para seus nomes de propriedade, mas os nomes de campo na coleção MongoDB usam Camel case. Para considerar essa diferença, você pode usar o seguinte código para registrar um ConventionPack quando o aplicativo iniciar:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
Para usar o driver MongoDB .NET/C# para adicionar um estágio $bucketAuto a um pipeline de agregação, chame o método BucketAuto() em um objeto PipelineDefinition.
O exemplo a seguir cria um estágio de pipeline que distribui uniformemente documentos em cinco buckets pelo valor de seu campo Runtime :
var pipeline = new EmptyPipelineDefinition<Movie>() .BucketAuto( groupBy: m => m.Runtime, buckets: 5);
Você pode usar um objeto AggregateBucketAutoOptions para especificar um esquema baseado em número preferencial para definir valores de limite. O exemplo a seguir executa a mesma operação $bucketAuto do exemplo anterior , mas também define os limites do bucket nas potências de 2:
var bucketAutoOptions = new AggregateBucketAutoOptions() { Granularity = new AggregateBucketAutoGranularity("POWERSOF2") }; var pipeline = new EmptyPipelineDefinition<Movie>() .BucketAuto( groupBy: m => m.Runtime, buckets: 5, options: bucketAutoOptions);
Os exemplos do Node.js nesta página utilizam o banco de dados do sample_mflix a partir dos conjuntos de dados de amostra do Atlas. Para saber como criar um cluster gratuito do MongoDB Atlas e carregar os conjuntos de dados de exemplo, consulte Introdução na documentação do driver do MongoDB Node.js
Para usar o driver Node.js do MongoDB para adicionar um estágio $bucketAuto a um pipeline de agregação , use o operador $bucketAuto em um objeto de pipeline.
O exemplo a seguir cria um estágio de pipeline que distribui uniformemente documentos em cinco buckets pelo valor de seu campo runtime . Em seguida, o exemplo executa o agregação pipeline:
const pipeline = [ { $bucketAuto: { groupBy: "$runtime", buckets: 5 } } ]; const cursor = collection.aggregate(pipeline); return cursor;
O exemplo a seguir executa a mesma operação $bucketAuto do exemplo anterior, mas define os limites do bucket como potências de 2 usando o parâmetro granularity:
const pipeline = [ { $bucketAuto: { groupBy: "$runtime", buckets: 5, granularity: "POWERSOF2" } } ]; const cursor = collection.aggregate(pipeline); return cursor;
Saiba mais
Para saber mais sobre os estágios de pipeline relacionados, consulte o guia$bucket.