Unique Indexes
Nesta página
Um índice único garante que os campos indexados não armazenam valores duplicados; isto é, impõe exclusividade para os campos indexados. Por padrão, o MongoDB cria um índice único no campo _id durante a criação de uma coleção.
Observação
Novo formato interno
A partir do MongoDB 4.2, para featureCompatibilityVersion (fCV) de 4.2 (ou superior), o MongoDB usa um novo formato interno para índices únicos que é incompatível com versões anteriores do MongoDB. O novo formato se aplica tanto a índices únicos existentes quanto a índices únicos recém-criados/reconstruídos.
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. Se você usar a restrição exclusiva em um índice composto, o MongoDB imporá exclusividade na combinação dos valores de chave de í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 collection durante o procedimento. Se você não puder parar todas as gravações na collection durante o procedimento, não use o procedimento contínuo. Em vez disso, crie seu índice único na collection com as seguintes ações:
emitindo
db.collection.createIndex()
no primário para um conjunto de réplicas ouemitir
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.
Para uma coleção fragmentada variada, somente os seguintes índices podem ser exclusivos:
o índice na chave de fragmentação
um índice composto onde a chave de fragmentação é um prefixo
O
_id
índice padrão; however, the_id
index only enforces the uniqueness constraint per shard if the_id
campo is not the shard key.
Importante
Os clusters fragmentados só forçam a restrição de exclusividade em campos _id
no cluster quando o campo _id
também é a chave de fragmento.
Se o campo _id
não for a chave de fragmento ou se for apenas o prefixo da chave de fragmento, a restrição de exclusividade se aplicará somente ao fragmento que armazena o documento. Isso significa que dois ou mais documentos podem ter o mesmo valor de _id
, desde que ocorram em shards diferentes.
Por exemplo, considere uma coleção fragmentada com chave de fragmento {x:
1}
que abranja dois fragmentos A e B. Como a chave _id
não é a chave de fragmento, a coleção pode ter um documento com o valor _id
1
no fragmento A e outro documento com valor _id
1
no fragmento B.
Nos casos em que o campo _id
não é a chave do fragmento, o MongoDB espera que os aplicativos forcem a exclusividade dos valores _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 a collection tiver vários índices únicos, a menos que a chave de shard seja o prefixo de todos os índices únicos.
Para uma collection já fragmentada, não é possível criar índices únicos em outros campos, a menos que a chave de shard seja incluída como prefixo.
Um índice único armazena um valor nulo para um documento sem o campo indexado ; ou seja, um campo de índice ausente é tratado como outra instância de um
null
valor de chave de índice. Para obter mais informações, consulte Campo de documento ausente em um índice exclusivo de campo único.
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 } )