Unique Indexes
Nesta página
Um índice único garante que os campos indexados não armazenem valores duplicados. Um índice único em um único campo garante que um valor apareça no máximo uma vez em determinado campo. Um índice composto exclusivo garante que qualquer combinação dos valores da chave do índice apareça apenas uma vez. Por padrão, o MongoDB cria um índice único no campo _id durante a criação de uma collection.
Você pode criar e gerenciar índices únicos na IU para implantações hospedadas no MongoDB Atlas.
Criar um índice único
Para criar um índice único, utilize o método db.collection.createIndex()
com a opção unique
definida como true
.
db.collection.createIndex( <key and index type specification>, { unique: true } )
Índice único em um único campo
Por exemplo, para criar um índice único no campo user_id
da coleção members
, utilize a seguinte operação em mongosh
:
db.members.createIndex( { "user_id": 1 }, { unique: true } )
Índice composto único
Você também pode impor uma restrição única em índices compostos. Um índice composto exclusivo impõe exclusividade na combinação dos valores de chave do índice.
Por exemplo, para criar um índice único nos campos groupNumber
, lastname
e firstname
da coleção members
, utilize a seguinte operação em mongosh
:
db.members.createIndex( { groupNumber: 1, lastname: 1, firstname: 1 }, { unique: true } )
O índice criado impõe exclusividade para a combinação de valores groupNumber
, lastname
e firstname
.
Para outro exemplo, considere uma collection com o seguinte documento:
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
Crie um índice composto único multikey em a.loc
e a.qty
:
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
O índice único permite a inserção dos seguintes documentos na collection, pois o índice impõe exclusividade para a combinação dos valores a.loc
e a.qty
:
db.collection.insertMany( [ { _id: 2, a: [ { loc: "A" }, { qty: 5 } ] }, { _id: 3, a: [ { loc: "A", qty: 10 } ] } ] )
Comportamento
Restrições
O MongoDB não pode criar um índice único no(s) campo(s) de índices especificado(s) se a coleção já contiver dados que violariam a restrição única para o índice.
Você não pode especificar uma restrição única em um índice hashed.
Criando um índice único em conjuntos de réplicas e clusters fragmentados
Para conjuntos de réplicas e clusters fragmentados, o uso de um procedimento contínuo para criar um índice único exige que você interrompa todas as gravações na coleção durante o procedimento. Se você não puder parar todas as gravações na coleção durante o procedimento, não use o procedimento contínuo. Em vez disso, para criar seu índice único na coleção, você deve:
Execute
db.collection.createIndex()
no primário para um conjunto de réplicasExecute
db.collection.createIndex()
nomongos
para um cluster fragmentado
Restrição exclusiva em documentos separados
A restrição exclusiva se aplica a documentos separados na collection. Ou seja, o índice único impede que documentos separados tenham o mesmo valor para a chave indexada.
Como a restrição se aplica a documentos separados, para um índice multichave exclusivo, um documento pode ter elementos de array que resultam na repetição de valores de chave de índice, desde que os valores de chave de índice desse documento não dupliquem os de outro documento. Neste caso, a entrada repetida do índice é inserida no índice apenas uma vez.
Por exemplo, considere uma collection com os seguintes documentos:
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] } { _id: 2, a: [ { loc: "A" }, { qty: 5 } ] } { _id: 3, a: [ { loc: "A", qty: 10 } ] }
Crie um índice único composto multichave em a.loc
e a.qty
:
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
O índice único permite inserir o seguinte documento na collection se nenhum outro documento da collection tiver um valor de chave de índice { "a.loc": "B", "a.qty": null }
.
db.collection.insertOne( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )
Campo de documento ausente em um índice único de campo único
Se um documento tiver valor null
ou ausente no campo indexado em um índice único de campo único, o índice armazenará um valor null
para esse documento. Devido à restrição exclusiva, um índice único de campo único só pode conter um documento que contenha um valor null
em sua entrada de índice. Se houver mais de um documento com valor null
em sua entrada de índice, a construção do índice apresentará um erro de chave duplicada.
Por exemplo, uma collection tem um índice único de campo único no x
:
db.collection.createIndex( { "x": 1 }, { unique: true } )
O índice único permite a inserção de um documento sem o campo x
se a collection ainda não contiver um documento sem o campo x
:
db.collection.insertOne( { y: 1 } )
No entanto, você não pode inserir um documento sem o campo x
se a collection já contiver um documento sem o campo x
:
db.collection.insertOne( { z: 1 } )
A operação falha ao inserir o documento devido à violação da restrição exclusiva no valor do campo x
:
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }" } })
Campos de documento ausentes em um índice único composto
Se um documento tiver valor null
ou ausente para um ou mais campos indexados em um índice composto único, o índice armazenará um valor nulo para cada null
ou campo ausente na entrada de índice do documento. Devido à restrição exclusiva, um índice composto único só permite um documento que tenha valor null
para todos os campos indexados em uma entrada de índice. Se houver mais de uma entrada de índice com valor null
para todos os campos indexados, a construção de índice apresentará um erro de chave duplicada. O MongoDB permite vários documentos com campos ausentes em índices compostos únicos desde que cada entrada de índice seja única.
Por exemplo, uma collection students
tem um índice único composto nos campos name
, age
e grade
:
db.students.createIndex( { "name": 1, "age": -1, "grade": 1 }, { unique: true } )
Se a collection ainda não contiver documentos idênticos, o índice único composto permitirá a inserção dos seguintes documentos que não possuem o campo grade
.
db.students.insertMany( { "name": "Meredith", "age": 12 }, { "name": "Olivia", "age": 11 }, { "name": "Benjamin" } )
No entanto, você não pode inserir um documento com a mesma chave de índice (valor para name
, age
e grade
) que outro documento na collection.
db.students.insertOne( { name: "Meredith", age: 12 } )
A operação falha ao inserir o documento devido à violação da restrição única nos valores dos campos name
, age
e grade
:
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error collection: test.students index: name_1_age_-1_grade_1 dup key: { name: "Meredith", age: 12, grade: null } } } )
Você também não pode inserir um documento que seja exclusivo, mas que compartilhe uma chave de índice com uma entrada de índice existente.
db.students.insertOne( { name: "Olivia", "age": 11, "favorite color": "red"} )
A operação falha ao inserir o documento devido à violação da restrição única nos valores dos campos name
, age
e grade
:
WriteResult({ "nInserted" : 0, "writeError" : { "code" : 11000, "errmsg" : "E11000 duplicate key error collection: test.students index: name_1_age_-1_grade_1 dup key: { name: "Olivia", age: 11, grade: null } } } )
Índices únicos parciais
Os índices parciais indexam apenas os documentos em uma coleção que atendem a uma expressão do filtro especificada. Se você especificar partialFilterExpression
e uma restrição exclusiva, a restrição exclusiva se aplicará apenas aos documentos que atendem à expressão do filtro.
Um índice parcial com uma restrição única não impede a inserção de documentos que não atendem à restrição única se os documentos não atenderem aos critérios do filtro. Para um exemplo, consulte Índice parcial com restrição única.
Clusters fragmentados e índices únicos
Você não pode especificar uma restrição única em um índice hash.
Em uma coleção fragmentada à distância, somente os seguintes índices podem ser únicos::
o índice na chave de fragmentação
um índice composto onde a chave de fragmentação é um prefixo
o índice
_id
padrão; entretanto, o índice_id
impõe a restrição de exclusividade por fragmento somente se o campo_id
não for a chave de fragmentação ou o prefixo da chave de fragmentação.Importante
Singularidade e o índice _id
Se o campo
_id
não for a chave de fragmentação ou o prefixo da chave de fragmentação, o índice_id
somente imporá a restrição de singularidade por fragmento, e não entre fragmentos.Por exemplo, considere uma collection fragmentada (com chave de fragmentação
{x: 1}
) que envolve dois fragmentos, A e B. Como a chave_id
não faz parte da chave de fragmentação, a collection pode ter um documento com_id
de valor1
no fragmento A, e outro documento com_id
de valor1
no fragmento B.Se o campo
_id
não for a chave de fragmentação nem o prefixo da chave de fragmentação, o MongoDB entende que as aplicações imporão a exclusividade dos valores de_id
nos fragmentos.
As restrições de índice único significam que:
Para uma collection que será fragmentada, você não poderá fragmentar a collection se ela tiver outros índices únicos.
Para uma collection já fragmentada, não é possível criar índices únicos em outros campos.
Para manter a exclusividade em um campo que não é sua chave de shard, consulte Restrições únicas em campos arbitrários.
Índices únicos esparsos e não esparsos
A partir do MongoDB 5.0, índices esparsos e não esparsos exclusivos com o mesmo padrão de chave podem existir em uma única collection.
Criação de índice único e esparso
Este exemplo cria vários índices com o mesmo padrão de chave e diferentes opções sparse
:
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )
Criação de índice básico e esparso
Você também pode criar índices básicos com o mesmo padrão de chave com e sem a opção esparsa:
db.scoreHistory.createIndex( { score : 1 }, { name: "sparse_index", sparse: true } ) db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )
Índices básicos e eúnicos com padrões de chave duplicados
A partir de MongoDB 5.0, índices básicos e únicos podem existir com o mesmo padrão de chave.
Essa duplicação nos padrões principais permite adicionar um índice único a campos já indexados.
Neste exemplo:
Crie um índice básico com o padrão-chave { score : 1 }
e insira três documentos.
db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } ) db.scoreHistory.insert( { score : 1 } ) db.scoreHistory.insert( { score : 2 } ) db.scoreHistory.insert( { score : 3 } )
Crie um índice único com o mesmo padrão de chave { score : 1 }
.
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )
Tente inserir um documento score
duplicado que falhe devido ao índice único.
db.scoreHistory.insert( { score : 3 } )