Índices curinga
Nesta página
O MongoDB oferece suporte à criação de índices em um campo ou conjunto de campos para oferecer suporte a query. Como o MongoDB oferece suporte a esquemas dinâmicos, a aplicação pode executar query do campo cujos nomes não podem ser conhecidos antecipadamente ou são arbitrários.
Novidade na versão MongoDB: 4,2
O MongoDB 4.2 introduz índices curinga para apoiar query em campo desconhecidos ou arbitrários.
Considere um aplicativo que captura dados definidos pelo usuário no campo userMetadata
e oferece suporte à consulta desses dados:
{ "userMetadata" : { "likes" : [ "dogs", "cats" ] } } { "userMetadata" : { "dislikes" : "pickles" } } { "userMetadata" : { "age" : 45 } } { "userMetadata" : "inactive" }
Os administradores desejam criar índices para dar suporte a query em qualquer subcampo de userMetadata
.
Um índice curinga em userMetadata
pode suportar query de campo único em userMetadata
, userMetadata.likes
, userMetadata.dislikes
e userMetadata.age
:
db.userData.createIndex( { "userMetadata.$**" : 1 } )
O índice suporta as seguintes queries:
db.userData.find({ "userMetadata.likes" : "dogs" }) db.userData.find({ "userMetadata.dislikes" : "pickles" }) db.userData.find({ "userMetadata.age" : { $gt : 30 } }) db.userData.find({ "userMetadata" : "inactive" })
Um índice não curinga em userMetadata
só pode suportar query em valores de userMetadata
.
Importante
Os índices curinga não são projetados para substituir o planejamento de índice baseado em volume de trabalho. Para obter mais informações sobre como criar índices para dar suporte a queries, consulte Criar índices para dar suporte a suas queries. Para obter a documentação completa sobre limitações de índice curinga , consulte Restrições de índice curinga.
Criar Índice Curinga
Importante
O mongod
featureCompatibilityVersion deve ser 4.2
para criar índices curinga. Para obter instruções sobre como definir o FCV, consulte Definir versão de compatibilidade do recurso em sistemas do MongoDB 5.0.
Você pode criar índices curinga utilizando o reconhecimento de data center createIndexes
ou seu assistente de shell, createIndex()
ou createIndexes()
.
Criar um Índice Curinga em um campo
Para indexar o valor de um campo específico:
db.collection.createIndex( { "fieldA.$**" : 1 } )
Com este índice curinga, o MongoDB indexa todos os valores de fieldA
. Se um campo for um documento ou array aninhado, o índice curinga recorrerá ao documento/array e armazenará o valor de todos os campos no documento/array.
Por exemplo, documentos na collection product_catalog
podem conter um campo product_attributes
. O campo product_attributes
pode conter campos aninhados arbitrários, incluindo documentos incorporados e arrays:
{ "product_name" : "Spy Coat", "product_attributes" : { "material" : [ "Tweed", "Wool", "Leather" ] "size" : { "length" : 72, "units" : "inches" } } } { "product_name" : "Spy Pen", "product_attributes" : { "colors" : [ "Blue", "Black" ], "secret_feature" : { "name" : "laser", "power" : "1000", "units" : "watts", } } }
A seguinte operação cria um índice curinga no campo product_attributes
:
db.products_catalog.createIndex( { "product_attributes.$**" : 1 } )
O índice curinga pode suportar query arbitrárias de campo único no product_attributes
ou seus campo embutidos:
db.products_catalog.find( { "product_attributes.size.length" : { $gt : 60 } } ) db.products_catalog.find( { "product_attributes.material" : "Leather" } ) db.products_catalog.find( { "product_attributes.secret_feature.name" : "laser" } )
Observação
A sintaxe do índice curinga específico do caminho é incompatível com a opção wildcardProjection
. Consulte as Opções para índices do wildcard
para mais informações.
Para obter um exemplo, consulte Criar um Índice Curinga em um caminho do campo.
Criar um Índice Curinga em Todos os Campos
Para indexar o valor de todos os campos em um documento (excluindo _id
), especifique "$**"
como a chave do índice:
db.collection.createIndex( { "$**" : 1 } )
Com esse índice curinga, o MongoDB indexa todos os campo para cada documento na collection. Se um determinado campo for um documento ou array aninhada, o índice curinga recorrerá ao documento/array e armazenará o valor de todos os campos no documento/array.
Para obter um exemplo, consulte Criar um Índice Curinga em Todos os Field Paths.
Observação
Os índices curinga omitem o campo _id
por padrão. Para incluir o campo _id
no índice curinga, você deve explicitamente incluí-lo no documento wildcardProjection
. Consulte Opções para índices wildcard
para obter mais informações.
Criar um índice curinga em vários campos específicos
Para indexar os valores de vários campos específicos em um documento:
db.collection.createIndex( { "$**" : 1 }, { "wildcardProjection" : { "fieldA" : 1, "fieldB.fieldC" : 1 } } )
Com esse índice curinga, o MongoDB indexa todos os valores para os campos especificados para cada documento na coleção. Se um determinado campo for um documento ou array aninhada, o índice curinga recorrerá ao documento/array e armazenará o valor de todos os campos no documento/array.
Observação
Os índices curinga não suportam a combinação de instruções de inclusão e exclusão no documento wildcardProjection
, exceto quando se inclui explicitamente o campo _id
. Para obter mais informações sobre wildcardProjection
, consulte as Opções para índices wildcard
.
Para obter um exemplo, consulte Incluir campos específicos na cobertura do índice curinga.
Criar um índice curinga que exclua vários campos específicos
Para indexar o campo de todos os campos em um documento, excluindo caminhos de campo específicos:
db.collection.createIndex( { "$**" : 1 }, { "wildcardProjection" : { "fieldA" : 0, "fieldB.fieldC" : 0 } } )
Com esse índice curinga, o MongoDB indexa todos os campo para cada documento na collection, excluindo os caminho do campo especificados. Se um determinado campo for um documento ou array aninhada, o índice curinga recorrerá ao documento/array e armazenará os valores de todos os campos no documento/array.
Para obter um exemplo, consulte Omitir campos específicos da cobertura do índice curinga.
Observação
Os índices curinga não suportam a combinação de instruções de inclusão e exclusão no documento wildcardProjection
, exceto quando se inclui explicitamente o campo _id
. Para obter mais informações sobre wildcardProjection
, consulte as Opções para índices wildcard
.
Visualizando índices curinga normalizados
A partir do MongoDB 5.0, os índices curinga são normalizados após a criação, vários índices curinga podem ser criados usando o mesmo padrão de chave , desde que os campos wildcardProjection não Express filtros equivalentes.
Por exemplo, crie um índice curinga:
db.books.createIndex( { "$**" : 1 }, { wildcardProjection : {a: 1, "b.c": 1 } } )
Visualizar o índice com o método db.collection.getIndexes()
:
db.books.getIndexes()
Os resultados são exibidos em um formato normalizado:
{ v: 2, key: { _id: 1 }, name: '_id_' }, { v: 2, key: { '$**': 1 }, name: '$**_1', wildcardProjection: { a: true, b: { c: true }, _id: false } }
Considerações
Os índices curinga podem suportar no máximo um campo em qualquer predicado de query fornecido. Para obter mais informações sobre o suporte da query do índice curinga, consulte Suporte da query/classificação do índice curinga.
O
mongod
featureCompatibilityVersion deve ser4.2
para criar índices curinga. Para obter instruções sobre como definir o FCV, consulte Definir versão de compatibilidade do recurso em sistemas do MongoDB 5.0.Os índices curinga omitem o campo _id por padrão. Para incluir o campo
_id
no índice curinga, você deve explicitamente incluí-lo no documento curingaProjection (ou seja,{ "_id" : 1 }
).É possível criar múltiplos índices curinga em uma coleção.
Um índice curinga pode cobrir os mesmos campos que outros índices na collection.
Os índices curinga são índices esparsos e contêm apenas entradas para documentos que têm o campo indexado, mesmo que o campo de índice contenha um valor nulo.
Comportamento
Os índices curinga têm um comportamento específico ao indexar campos que são um objeto (ou seja, um documento incorporado) ou uma array:
Se o campo for um objeto, o índice curinga desce para o objeto e indexa seu conteúdo. O índice curinga continua descendo para quaisquer documentos incorporados adicionais que encontrar.
Se o campo for uma array, o índice curinga atravessará a array e indexará cada elemento:
Se um elemento na array for um objeto, o índice curinga desce até o objeto para indexar seu conteúdo, conforme descrito acima.
Se o elemento for uma array - ou seja, uma array incorporada diretamente na array principal -, o índice curinga não atravessará a array incorporada, mas indexará a array inteira como um único valor.
Para todos os outros campos, registre o valor primitivo (não objeto/array) no índice.
O índice curinga continua atravessando quaisquer objetos ou arrays aninhados adicionais até atingir um valor primitivo (ou seja, um campo que não é um objeto ou array). Em seguida, ele indexa esse valor primitivo, juntamente com o caminho completo para esse campo.
Por exemplo, considere o seguinte documento:
{ "parentField" : { "nestedField" : "nestedValue", "nestedObject" : { "deeplyNestedField" : "deeplyNestedValue" }, "nestedArray" : [ "nestedArrayElementOne", [ "nestedArrayElementTwo" ] ] } }
Um índice curinga que inclui parentField
registra as seguintes entradas:
"parentField.nestedField" : "nestedValue"
"parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"
"parentField.nestedArray" : "nestedArrayElementOne"
"parentField.nestedArray" : ["nestedArrayElementTwo"]
Observe que os registros de parentField.nestedArray
não incluem a posição da array para cada elemento. Os índices curinga ignoram as posições dos elementos da array ao gravar o elemento no índice. Os índices curinga ainda podem suportar queries que incluem índices de array explícitos. Consulte Queries com índices de array explícitos para obter mais informações.
Para obter mais informações sobre o comportamento do índice curinga com objetos aninhados, consulte Objetos aninhados.
Para obter mais informações sobre o comportamento do índice curinga com arrays agrupadas, consulte Arrays agrupadas.
objeto aninhados
Quando um índice curinga encontra um objeto aninhado, ele desce até o objeto e indexa seu conteúdo. Por exemplo:
{ "parentField" : { "nestedField" : "nestedValue", "nestedArray" : ["nestedElement"] "nestedObject" : { "deeplyNestedField" : "deeplyNestedValue" } } }
Um índice curinga que inclui parentField
desce para o objeto para percorrer e indexar seu conteúdo:
Para cada campo que é um objeto (ou seja, um documento incorporado), desça ao objeto para indexar seu conteúdo.
Para cada campo que é uma array, percorra a array e indexe seu conteúdo.
Para todos os outros campos, registre o valor primitivo (não objeto/array) no índice.
O índice curinga continua atravessando quaisquer objetos ou arrays aninhados adicionais até atingir um valor primitivo (ou seja, um campo que não é um objeto ou array). Em seguida, ele indexa esse valor primitivo, juntamente com o caminho completo para esse campo.
Dado o documento de exemplo, o índice curinga adiciona os seguintes registros ao índice:
"parentField.nestedField" : "nestedValue"
"parentField.nestedObject.deeplyNestedField" : "deeplyNestedValue"
"parentField.nestedArray" : "nestedElement"
Para obter mais informações sobre o comportamento do índice curinga com arrays agrupadas, consulte Arrays agrupadas.
Arrays agrupadas
Quando um índice curinga encontra uma array agrupada, ele tenta atravessar a array para indexar seus elementos. Se a array for em si um elemento em uma array principal (ou seja, uma array incorporada), o índice curinga registrará a array inteira como um valor em vez de percorrer seu conteúdo. Por exemplo:
{ "parentArray" : [ "arrayElementOne", [ "embeddedArrayElement" ], "nestedObject" : { "nestedArray" : [ "nestedArrayElementOne", "nestedArrayElementTwo" ] } ] }
Um índice curinga que inclui parentArray
desce para a array para percorrer e indexar seu conteúdo:
Para cada elemento que é uma array (ou seja, uma array embutida), indexe a array inteira como um valor.
Para cada elemento que é um objeto, desça ao objeto para percorrer e indexar seu conteúdo.
Para todos os outros campos, registre o valor primitivo (não objeto/array) no índice.
O índice curinga continua atravessando quaisquer objetos ou arrays aninhados adicionais até atingir um valor primitivo (ou seja, um campo que não é um objeto ou array). Em seguida, ele indexa esse valor primitivo, juntamente com o caminho completo para esse campo.
Dado o documento de exemplo, o índice curinga adiciona os seguintes registros ao índice:
"parentArray" : "arrayElementOne"
"parentArray" : ["embeddedArrayElement"]
"parentArray.nestedObject.nestedArray" : "nestedArrayElementOne"
"parentArray.nestedObject.nestedArray" : "nestedArrayElementTwo"
Observe que os registros de parentField.nestedArray
não incluem a posição da array para cada elemento. Os índices curinga ignoram as posições dos elementos da array ao gravar o elemento no índice. Os índices curinga ainda podem suportar queries que incluem índices de array explícitos. Consulte Queries com índices de array explícitos para obter mais informações.
Exibição de Índice
A partir do MongoDB 5.0.16, o campo wildcardProjection
armazena a projeção do índice na forma enviada. Versões anteriores do servidor podem ter armazenado a projeção de forma normalizada.
O servidor utiliza o índice da mesma maneira, mas você pode notar uma diferença na saída dos comandos listIndexes
e db.collection.getIndexes()
.
Restrições
Você não pode fragmentar uma collection usando um índice curinga. Crie um índice não curinga no campo ou campos que você deseja fragmentar. Para obter mais informações sobre a seleção de chaves de shard, consulte Chaves de Shard.
Não é possível criar um índice composto .
Não é possível especificar as seguintes propriedades para um índice curinga:
Não é possível criar os seguintes tipos de índice utilizando a sintaxe curinga:
Importante
Os índices curinga são distintos e incompatíveis com os índices de texto curinga. Os índices curinga não suportam consultas usando o operador $text
.
Para obter a documentação completa sobre restrições de criação de índice curinga, consulte Tipos de índice ou propriedades incompatíveis.
Suporte de query/classificação de índice curinga
Queries cobertas
Os índices curinga poderão suportar uma consulta coberta somente se todos os itens a seguir forem verdadeiros:
O planejador de query seleciona o índice curinga para satisfazer o predicado da query.
O predicado de consulta especifica exatamente um campo coberto pelo índice curinga.
A projeção exclui explicitamente o
_id
e inclui somente o campo de query.O campo de consulta especificado nunca é uma matriz.
Considere o seguinte índice curinga na collection employees
:
db.products.createIndex( { "$**" : 1 } )
A seguinte operação faz uma consulta para um campo único lastName
e projeta todos os outros campos a partir do documento resultante:
db.products.find( { "lastName" : "Doe" }, { "_id" : 0, "lastName" : 1 } )
Supondo que o lastName
especificado nunca seja uma array, o MongoDB pode usar o índice curinga $**
para oferecer suporte a uma query coberta.
Predicados de query de vários campos
Os índices curinga podem suportar no máximo um campo de predicado de query. Ou seja:
O MongoDB não pode usar um índice não curinga para satisfazer uma parte de um predicado de query e um índice curinga para satisfazer outro.
O MongoDB não pode usar um índice curinga para satisfazer uma parte de um predicado de query e outro índice curinga para satisfazer outro.
Mesmo que um único índice curinga possa suportar vários campos de query, o MongoDB pode usar o índice curinga para suportar apenas um dos campos de query. Todos os campos restantes são resolvidos sem um índice.
No entanto, o MongoDB pode usar o mesmo índice curinga para satisfazer cada argumento independente dos operadores de query $or
ou aggregation $or
.
Consultas com Classificação
O MongoDB pode usar um índice curinga para satisfazer sort()
somente se todas as condições a seguir forem verdadeiras:
O planejador de query seleciona o índice curinga para satisfazer o predicado da query.
O
sort()
especifica somente o campo de predicado da query.O campo especificado nunca é uma matriz.
Se as condições acima não forem atendidas, o MongoDB não poderá usar o índice curinga para a classificação. O MongoDB não suporta operações do sort()
que exigem um índice diferente do do predicado de query. Para obter mais informações, consulte Interseção e classificação de índices.
Considere o seguinte índice curinga na collection products
:
db.products.createIndex( { "product_attributes.$**" : 1 } )
A seguinte operação faz queries para um campo único product_attributes.price
e classifica neste mesmo campo:
db.products.find( { "product_attributes.price" : { $gt : 10.00 } }, ).sort( { "product_attributes.price" : 1 } )
Supondo que o price
especificado nunca seja uma array, o MongoDB pode usar o índice curinga product_attributes.$**
para satisfazer tanto find()
quanto sort()
.
Padrões de query não suportados
Os índices curinga não podem suportar os seguintes padrões de query:
Query que verificam se um campo não existe
Query que verificam se um campo é ou não igual a um documento ou array
Query que verificam se um campo é igual a nulo
Para obter detalhes, consulte Padrões de query e aggregation não suportados.
Consultas com índices de array explícitos
Os índices curinga do MongoDB não registram a posição da array de nenhum elemento específico em uma array durante a indexação. No entanto, o MongoDB ainda pode selecionar o índice curinga para responder a uma query que inclui um caminho do campo com um ou mais índices de array explícitos (por exemplo, parentArray.0.nestedArray.0
). Devido à crescente complexidade de definir limites de índice para cada array aninhada consecutiva, o MongoDB não considera que o índice curinga responda a um determinado caminho do campo na query se esse caminho contiver mais de 8
índices de array explícitos. O MongoDB ainda pode considerar o índice curinga para responder a outros caminhos de campo na query.
Por exemplo:
{ "parentObject" : { "nestedArray" : [ "elementOne", { "deeplyNestedArray" : [ "elementTwo" ] } ] } }
O MongoDB pode selecionar um índice curinga que inclua parentObject
para satisfazer as seguintes query:
"parentObject.nestedArray.0" : "elementOne"
"parentObject.nestedArray.1.deeplyNestedArray.0" : "elementTwo"
Se um determinado caminho do campo no predicado de query especificar mais de 8 índices de array explícitos, o MongoDB não considerará o índice curinga para responder a esse caminho do campo. Em vez disso, o MongoDB seleciona outro índice elegível para responder à query ou executa uma varredura de collection.
Observe que os índices curinga em si não têm limites na profundidade com que atravessam um documento enquanto o indexam; a limitação se aplica apenas a query que especificam explicitamente índices de array exatos. Ao emitir as mesmas queries sem os índices de array explícitos, o MongoDB pode selecionar o índice curinga para responder à query:
"parentObject.nestedArray" : "elementOne"
"parentObject.nestedArray.deeplyNestedArray" : "elementTwo"