Menu Docs
Página inicial do Docs
/ / /
Kotlin Coroutine
/

Agrupamentos

Nesta página

  • Visão geral
  • Dados de amostra para exemplos
  • Agrupamentos no MongoDB
  • Como especificar agrupamentos
  • collection
  • Índice
  • (operação)
  • Tipos de índice que não suportam agrupamentos
  • Opções de agrupamento
  • Exemplos de agrupamento
  • Exemplo de find() e sort()
  • Exemplo de findOneAndUpdate ()
  • Exemplo de findOneAndDelete()
  • Exemplo de agregação

Neste guia, você pode aprender como usar agrupamentos com MongoDB para ordenar sua query ou resultados de operação de agregação por valores de string. Um agrupamento é um conjunto de regras de ordenação e correspondência de caracteres que se aplicam a um idioma e uma localidade específicos.

Você pode saber mais sobre agrupamentos nas seguintes seções deste guia:

  • Agrupamentos no MongoDB

  • Como especificar agrupamentos

  • Opções de agrupamento

  • Exemplos de códigos de agrupamento

Os exemplos desta página usam uma coleção do MongoDB com os seguintes documentos:

{ "_id" : 1, "firstName" : "Klara" }
{ "_id" : 2, "firstName" : "Gunter" }
{ "_id" : 3, "firstName" : "Günter" }
{ "_id" : 4, "firstName" : "Jürgen" }
{ "_id" : 5, "firstName" : "Hannah" }

Esses documentos são representados pela seguinte classe de dados:

data class FirstName(
@BsonId val id: Int,
val firstName: String,
val verified: Boolean = false
)

O MongoDB classifica strings utilizando agrupamento binário por padrão. O agrupamento binário usa o padrão ASCII valores de caracteres para comparar e ordenar strings. Determinados idiomas e localidades possuem convenções específicas de ordenação de caracteres que diferem dos valores de caracteres ASCII.

Por exemplo, no francês canadense, o caractere mais acentuado à direita (diacrítico) determina a ordem das strings quando todos os caracteres anteriores são iguais. Considere as seguintes palavras em francês canadense:

  • cote

  • coté

  • côte

  • côté

Ao usar o agrupamento binário, o MongoDB os classifica na seguinte ordem:

cote
coté
côte
côté

Ao usar o agrupamento em francês canadense, o MongoDB os classifica em uma ordem diferente, conforme mostrado abaixo:

cote
côte
coté
côté

O MongoDB suporta agrupamentos na maioria dasoperações e agregações CRUD . Para obter uma lista completa das operações suportadas, consulte a página de manual do servidor Operações que suportam agrupamentos .

Você pode especificar o código de localidade e a variante opcional no seguinte formato de string:

"<locale code>@collation=<variant code>"

O exemplo a seguir especifica o código de localidade "de" e o código da variante "phonebook":

"de@collation=phonebook"

Se você não precisar especificar uma variante, omita tudo após o código de localidade da seguinte forma:

"de"

Para obter uma lista completa dos locais suportados, consulte a página do manual do servidor em Idiomas e locais suportados.

As seções a seguir mostram maneiras diferentes de aplicar agrupamentos no MongoDB:

Você pode definir um agrupamento padrão ao criar uma collection. Quando você cria uma collection com um agrupamento especificado, todas as operações suportadas que verificam essa collection aplicam as regras do agrupamento.

Você só pode atribuir um agrupamento padrão a uma coleção ao criar essa coleção. No entanto, você pode especificar um agrupamento em um novo índice em uma coleção existente. Consulte a seção Índice deste guia para obter mais informações.

O trecho a seguir mostra como especificar o agrupamento de localidade "en_US" ao criar uma nova collection chamada items:

database.createCollection(
"names",
CreateCollectionOptions().collation(
Collation.builder().locale("en_US").build()
)
)

Para verificar se você criou o agrupamento com sucesso, recupere uma lista dos índices nessa coleção da seguinte maneira:

val collection = database.getCollection<FirstName>("names")
val indexInformation = collection.listIndexes().first()
println(indexInformation.toJson())
{
// ...
"collation": {
"locale": "en_US",
// ...
},
// ...
}

Você pode especificar um agrupamento ao criar um novo índice em uma collection. O índice armazena uma representação ordenada dos documentos na collection para que sua operação não precise realizar a ordenação na memória. Para usar o índice, sua operação deve atender aos seguintes critérios:

  • A operação usa o mesmo agrupamento especificado no índice.

  • A operação é coberta pelo índice que contém o agrupamento.

O seguinte trecho de código mostra como você pode criar um índice no campo "firstName" com o agrupamento de localidade "en_US" em ordem crescente:

val collection = database.getCollection<FirstName>("names")
val idxOptions = IndexOptions().collation(Collation.builder().locale("en_US").build())
collection.createIndex(Indexes.ascending(FirstName::firstName.name), idxOptions)

Para verificar se você criou o agrupamento com sucesso, recupere uma lista dos índices nessa coleção da seguinte maneira:

val collection = database.getCollection<FirstName>("names")
val indexInformation = collection.listIndexes().first()
println(indexInformation.toJson())
{
// ...
"collation": {
"locale": "en_US",
// ...
},
// ...
}

O seguinte trecho de código mostra uma operação de exemplo que especifica o mesmo agrupamento e é coberta pelo índice que criamos no trecho de código anterior:

val resultsFlow = collection.find()
.collation(Collation.builder().locale("en_US").build())
.sort(Sorts.ascending(FirstName::firstName.name));

Você pode substituir o agrupamento padrão em uma collection passando o novo agrupamento como parâmetro para uma das operações aceitas. No entanto, como a operação não usa um índice, a operação pode não funcionar tão bem quanto uma coberta por um índice. Para obter mais informações sobre as desvantagens das operações de classificação não cobertas por um índice, consulte a página do manual do servidor sobre Usar índices para classificar resultados de queries.

O seguinte trecho de código mostra um exemplo de operação de query com as seguintes características:

  • A coleção referenciada contém o agrupamento padrão "en_US" semelhante ao especificado na seção Coleções.

  • A query especifica o agrupamento Islandês ("é"), que não é coberto pelo índice de agrupamento padrão da collection.

  • Como o agrupamento especificado não é coberto por um índice, a operação de classificação é executada na memória.

val findFlow = collection.find()
.collation(Collation.builder().locale("is").build())
.sort(Sorts.ascending(FirstName::firstName.name))

Embora a maioria dos tipos de índice MongoDB ofereça suporte ao agrupamento, os seguintes tipos oferecem suporte somente à comparação binária:

Esta seção aborda várias opções de agrupamento e como especificá-las para refinar ainda mais o comportamento de ordenação e correspondência.

Opção de agrupamento
Descrição
localidade
Required. The ICU locale code for language and variant.
locale() API Documentation
de trás para frente
Whether to consider diacritics from the end of the string first.
backwards() API Documentation
Sensibilidade a maiúsculas e minúsculas
Whether to consider case (upper or lower) as different values.
caseLevel() API Documentation
alternar
Whether to consider spaces and punctuation.
collationAlternate() API Documentation
caseFirst
Whether to consider uppercase or lowercase first.
collationCaseFirst() API Documentation
Variável máxima
Whether to ignore whitespace or both whitespace and punctuation. This setting is only valid when the alternate setting is "shifted".
collationMaxVariable() API Documentation
força
ICU level of comparison. The default value is "tertiary". For more information on each level, see the ICU Comparison Levels.
collationStrength() API Documentation
normalização
Whether to perform unicode normalization on the text as needed. For more information on unicode normalization, see Unicode Normalization Forms.
normalization() API Documentation
numericOrdering
Whether to order numbers according to numeric value rather than collation order.
numericOrdering() API Documentation

Você pode usar a classe Collation.Builder para especificar valores para as opções de agrupamento anteriores. Você pode chamar o método build() para construir um objeto Collation como mostrado no seguinte trecho de código:

Collation.builder()
.caseLevel(true)
.collationAlternate(CollationAlternate.SHIFTED)
.collationCaseFirst(CollationCaseFirst.UPPER)
.collationMaxVariable(CollationMaxVariable.SPACE)
.collationStrength(CollationStrength.SECONDARY)
.locale("en_US")
.normalization(false)
.numericOrdering(true)
.build()

Para obter mais informações sobre os métodos e parâmetros correspondentes que eles usam, consulte a documentação da API para Collation.Builder.

Esta seção contém exemplos que demonstram como usar uma seleção de operações do MongoDB que suportam agrupamentos.

Nos exemplos a seguir, especificamos a localidade "de@collation=phonebook" e o agrupamento de variantes. A parte "de" do agrupamento especifica a localidade alemão e a parte "agrupamento=phonebook" especifica uma variante. O agrupamento de localidades "de" contém regras para priorizar nomes próprios, identificados pela capitalização da primeira letra. Na variante "collation=phonebook", os caracteres com umlauts são ordenados antes dos mesmos caracteres sem eles em uma classificação crescente.

O exemplo a seguir demonstra como você pode aplicar um agrupamento ao recuperar resultados classificados de uma collection. Para executar esta operação, chame find() na collection de exemplo e encadeie os métodos collation() e sort() para especificar a ordem na qual você deseja receber os resultados.

Quando executamos esta operação em nossa coleção de exemplo, o resultado deve se assemelhar ao seguinte:

val resultsFlow = collection.find()
.collation(Collation.builder().locale("de@collation=phonebook").build())
.sort(Sorts.ascending(FirstName::firstName.name))
resultsFlow.collect { println(it) }
FirstName(id=3, firstName=Günter, verified=false)
FirstName(id=2, firstName=Gunter, verified=false)
FirstName(id=5, firstName=Hannah, verified=false)
FirstName(id=4, firstName=Jürgen, verified=false)
FirstName(id=1, firstName=Klara, verified=false)

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Esta seção mostra como especificar um agrupamento em uma operação que atualiza o primeiro resultado correspondente à sua consulta. Para especificar o agrupamento para essa operação, instancie um objeto FindOneAndUpdateOptions, defina um agrupamento nele e use-o como parâmetro ao chamar o método findOneAndUpdate() .

Neste exemplo, demonstramos o seguinte:

  • Recupere o primeiro documento em nossa coleção de exemplo que precede "Gunter" em uma ordem ascendente.

  • Defina as opções de operação, incluindo o agrupamento "de@collation=phonebook" .

  • Adicione um novo campo "verified" com o valor "true".

  • Recupere e imprima o documento atualizado.

Observação

O seguinte exemplo de código utiliza importações do pacote import com.mongodb.client.model para conveniência.

Como "Günter" está lexicalmente antes de "Gunter" usando o agrupamento de@collation=phonebook em ordem crescente, a operação a seguir retorna "Günter" antes de "Gunter" nos resultados:

val result = collection.findOneAndUpdate(
Filters.lt(FirstName::firstName.name, "Gunter"),
Updates.set("verified", true),
FindOneAndUpdateOptions()
.collation(Collation.builder().locale("de@collation=phonebook").build())
.sort(Sorts.ascending(FirstName::firstName.name))
.returnDocument(ReturnDocument.AFTER)
)
println(result)
FirstName(id=3, firstName=Günter, verified=true)

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Esta seção demonstra como você pode especificar uma ordenação numérica de strings em um agrupamento em uma operação que exclui a primeira correspondência da sua query. Para especificar o agrupamento para esta operação, instancie um objeto FindOneAndDeleteOptions , defina um agrupamento de ordem numérica nele e passe-o como um parâmetro para sua chamada ao método findOneAndDelete() .

Este exemplo chama a operação findOneAndDelete() em uma collection que contém os seguintes documento:

{ "_id" : 1, "a" : "16 apples" }
{ "_id" : 2, "a" : "84 oranges" }
{ "_id" : 3, "a" : "179 bananas" }

Esses documentos são representados pela seguinte classe de dados:

data class CollationExample(@BsonId val id: Int, val a: String)

No agrupamento, definimos a opção locale como "en" e a opção numericOrdering como "true" para classificar as strings com base em sua ordem numérica.

Observação

O seguinte exemplo de código utiliza importações do pacote import com.mongodb.client.model para conveniência.

val result = collection.findOneAndDelete(
Filters.gt(CollationExample::a.name, "100"),
FindOneAndDeleteOptions()
.collation(Collation.builder().locale("en").numericOrdering(true).build())
.sort(Sorts.ascending(CollationExample::a.name))
)
println(result)
CollationExample(id=3, a=179 bananas)

O valor numérico da string "179" é maior que o número 100, portanto, o documento anterior é a única correspondência.

Se executarmos a mesma operação sem o agrupamento de ordenação numérica na coleção original de três documentos, o filtro corresponderá a todos os nossos documentos, já que "100" vem antes de "16", "84" e "179" quando ordenados por agrupamento binário.

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Esta seção demonstra como você pode especificar um agrupamento em uma operação de agregação. Em uma operação de agregação, você pode especificar uma série de estágios de agregação que são chamados coletivamente de pipeline de agregação. Para executar uma agregação, chame o método aggregate() em um objeto MongoCollection .

Para especificar um agrupamento para uma operação de agregação, chame o método collation() no AggregateFlow retornado pela operação de agregação. Certifique-se de especificar um estágio de agregação de classificação no qual aplicar o agrupamento em seu pipeline de agregação.

O exemplo a seguir mostra como podemos construir um pipeline de agregação na coleção de exemplo e aplicar um agrupamento especificando o seguinte:

  • Um estágio de agregação de grupo usando o auxiliar Aggregates.group() para identificar cada documento pelo campo firstName e usar esse valor como _id do resultado.

  • Um acumulador no estágio de agregação de grupo para somar o número de instâncias de valores correspondentes no campo firstName .

  • Aplique uma classificação ascendente ao campo _id dos documentos de saída do estágio de agregação anterior.

  • Construa um objeto de agrupamento, especificando a localidade alemã e uma força de agrupamento que ignora acentos e umlauts.

data class Result(@BsonId val id: String, val nameCount: Int)
val groupStage = Aggregates.group(
"\$${FirstName::firstName.name}",
Accumulators.sum("nameCount", 1)
)
val sortStage = Aggregates.sort(Sorts.ascending("_id"))
val resultsFlow = collection.aggregate<Result>(listOf(groupStage, sortStage))
.collation(
Collation.builder().locale("de")
.collationStrength(CollationStrength.PRIMARY)
.build()
)
resultsFlow.collect { println(it) }
Result(id=Gunter, nameCount=2)
Result(id=Hannah, nameCount=1)
Result(id=Jürgen, nameCount=1)
Result(id=Klara, nameCount=1)

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Voltar

Transações

Próximo

Exploração madeireira