Menu Docs
Página inicial do Docs
/
Manual do MongoDB
/ /

Índices únicos

Nesta página

  • Criar um índice único
  • Comportamento

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

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 UI para sistemas hospedados no MongoDB Atlas.

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

Por exemplo, para criar um índice único no campo user_id da collection members , utilize a seguinte operação em mongosh:

db.members.createIndex( { "user_id": 1 }, { unique: true } )

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 collection 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 } ] }
] )

Dica

Veja também:

O MongoDB não pode criar um índice único nos campos de índice especificados se a collection já contiver dados que violariam a restrição exclusiva do índice.

Você não pode especificar uma restrição única em um índice hashed.

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:

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

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

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

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.

Você não pode especificar uma restrição única em um índice hash.

Para uma collection 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 valor 1 no fragmento A, e outro documento com _id de valor 1 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.

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.

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

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

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 } )
← Expirar dados de coleções definindo TTL