Menu Docs

Página inicial do DocsDesenvolver aplicaçõesMongoDB DriversDriver de sincronização Java

Agrupamentos

Nesta página

  • Visão geral
  • 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

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:

  • aprisco

  • 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 oferece suporte a agrupamentos na maioria das operações CRUD e agregações. 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 estiver especificando 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 collection ao criá-la. No entanto, você pode especificar um agrupamento em um novo índice em uma coleta 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(
"items",
new 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:

MongoCollection<Document> collection = database.getCollection("items");
List<Document> indexes = new ArrayList<>();
collection.listIndexes().into(indexes);
// Prints the collection's indexes and any default collations
indexes.forEach(idx -> System.out.println(idx.toJson()));

A saída do seu código deve conter o seguinte:

{ ...
"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 execute 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 "nome" com o agrupamento de localidade "en_US" em ordem crescente:

MongoCollection<Document> collection = database.getCollection("items");
IndexOptions idxOptions = new IndexOptions();
// Defines options that set a collation locale
idxOptions.collation(Collation.builder().locale("en_US").build());
// Creates an index on the "name" field with the collation and ascending sort order
collection.createIndex(Indexes.ascending("name"), idxOptions);

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

MongoCollection<Document> collection = database.getCollection("items");
List<Document> indexes = new ArrayList<>();
collection.listIndexes().into(indexes);
// Prints the collection's indexes and any default collations
indexes.forEach(idx -> System.out.println(idx.toJson()));

A saída do código anterior deve conter o seguinte:

{ ...
"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:

FindIterable<Document> cursor = collection.find()
.collation(Collation.builder().locale("en_US").build())
.sort(Sorts.ascending("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.

FindIterable<Document> cursor = collection.find()
.collation(Collation.builder().locale("is").build())
.sort(Sorts.ascending("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
Obrigatório. O código de localidade da ICU para idioma e variante.
locale() Documentação da API
de trás para frente
Se deve considerar primeiro os diacríticos do final da string.
de trás para frente() Documentação da API
Sensibilidade a maiúsculas e minúsculas
Se deve considerar maiúsculas e minúsculas (superior ou inferior) como valores diferentes.
caseLevel() Documentação da API
alternar
Se deve considerar espaços e pontuação.
collectionAlterne() Documentação da API
caseFirst
Se deve considerar maiúsculas ou minúsculas primeiro.
agrupamentoCaseFirst() Documentação da API
Variável máxima
Se deve ignorar o espaço em branco ou o espaço em branco e a pontuação. Esta configuração só é válida quando a configuração alternativa é "deslocada".
agrupamentoMaxVariable() Documentação da API
força
Nível de comparação da UTI. O valor padrão é "terciário". Para obter mais informações sobre cada nível, consulte Níveis de Comparação de ICU .
collectionStrength() Documentação da API
normalização
Se a normalização unicode deve ser executada no texto conforme necessário. Para obter mais informações sobre normalização unicode, consulte Formulários de normalização unicode .
normalização() Documentação da API
numericOrdering
Sobre a ordenação dos números de acordo com o valor numérico em vez da ordem de agrupamento.
numericOrdering() Documentação da API

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. Para cada exemplo, suponha que você comece com a seguinte collection de documento:

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

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.

Observação

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

List<Document> results = new ArrayList<>();
// Retrieves all documents and applies a "de@collation-phonebook" collation and ascending sort to the results
collection.find()
.collation(Collation.builder().locale("de@collation=phonebook").build())
.sort(Sorts.ascending("first_name")).into(results);
// Prints the JSON representation of the results
if (results != null) {
results.forEach(doc -> System.out.println(doc.toJson()));
}

Quando você executa esta operação na coleção de exemplo, a saída se assemelha ao seguinte:

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

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 ordem crescente.

  • 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.

Document result = collection.findOneAndUpdate(
Filters.gt("first_name", "Gunter"),
Updates.set("verified", true),
new FindOneAndUpdateOptions()
.collation(Collation.builder().locale("de@collation=phonebook").build())
.sort(Sorts.ascending("first_name"))
.returnDocument(ReturnDocument.AFTER));
// Prints the JSON representation of the updated document if an update occurred
if (result != null) {
System.out.println("Updated document: " + result.toJson());
}

Como "Günter" vem lexicalmente antes de "Gunter" usando o agrupamento de@collation=phonebook em ordem crescente, a operação anterior retorna o seguinte documento de atualização:

{
lastErrorObject: { updatedExisting: true, n: 1 },
value: { _id: 3, first_name: 'Günter' },
ok: 1
}

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" }

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.

Document result = collection.findOneAndDelete(
Filters.gt("a", "100"),
new FindOneAndDeleteOptions()
.collation(
Collation.builder()
.locale("en")
.numericOrdering(true)
.build())
.sort(Sorts.ascending("a")));
// Prints the JSON representation of the deleted document
if (result != null) {
System.out.println("Deleted document: " + result.toJson());
}

Depois de executar a operação anterior, seu resultado será semelhante ao seguinte:

Deleted document: {"_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 AggregateIterable 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 first_name 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 first_name .

  • 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.

Bson groupStage = Aggregates.group("$first_name", Accumulators.sum("nameCount", 1));
Bson sortStage = Aggregates.sort(Sorts.ascending("_id"));
AggregateIterable<Document> results = collection
// Runs the aggregation pipeline that includes tallying "first_name" frequencies
.aggregate(Arrays.asList(groupStage, sortStage))
// Applies a collation to sort documents alphabetically by using the German locale, ignoring accents
.collation(Collation.builder().locale("de").collationStrength(CollationStrength.PRIMARY).build());
// Prints the JSON representation of the results
if (results != null) {
results.forEach(doc -> System.out.println(doc.toJson()));
}

O código anterior gera os seguintes documentos:

{"_id": "Gunter", "nameCount": 2}
{"_id": "Hannah", "nameCount": 1}
{"_id": "Jürgen", "nameCount": 1}
{"_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:

← Índices