Unique Indexes

在本页面

唯一索引可确保索引字段不存储重复值;即对索引字段实施唯一性。默认情况下,MongoDB 在创建集合期间会在_id字段上创建唯一索引。

创建唯一索引

要创建唯一索引,请使用db.collection.createIndex()方法并将unique选项设置为true

db.collection.createIndex( <key and index type specification>, { unique: true } )

单个字段上的唯一索引

例如,要在members集合的user_id字段上创建唯一索引,请在mongo shell 中使用以下操作:

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

唯一复合索引

您还可以对compound indexes实施唯一约束。如果对compound index使用唯一约束,则 MongoDB 将对索引键值的* combination *强制执行唯一性。

例如,要在members集合的groupNumberlastnamefirstname字段上创建唯一索引,请在mongo shell 中使用以下操作:

db.members.createIndex( { groupNumber: 1, lastname: 1, firstname: 1 }, { unique: true } )

创建的索引对groupNumberlastnamefirstname值的组合强制具有唯一性。

对于另一个示例,请考虑包含以下文档的集合:

{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }

a.loca.qty上创建唯一的化合物multikey索引:

db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )

唯一索引允许将以下文档插入集合中,因为该索引对a.loca.qty值的组合强制具有唯一性:

db.collection.insert( { _id: 2, a: [ { loc: "A" }, { qty: 5 } ] } )
db.collection.insert( { _id: 3, a: [ { loc: "A", qty: 10 } ] } )

Behavior

Restrictions

如果集合已经包含违反索引唯一约束的数据,则 MongoDB 无法在指定的索引字段上创建unique index

您不能在hashed index上指定唯一约束。

在副本集和分片群集上构建唯一索引

对于副本集和分片群集,使用rolling procedure创建唯一索引要求您在此过程中停止对集合的所有写操作。如果在此过程中无法停止对集合的所有写操作,请不要使用滚动过程。而是通过以下方式在集合上构建唯一索引:

跨单独文档的唯一约束

唯一约束适用于集合中的单独文档。也就是说,唯一索引可防止分离文档的索引键具有相同的值。

因为该约束适用于单独的文档,所以对于唯一的multikey索引,文档可能具有导致重复索引键值的数组元素,只要该文档的索引键值不与另一个文档的索引键值重复即可。在这种情况下,重复的索引条目仅插入索引一次。

例如,考虑具有以下文档的集合:

{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] }
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }

a.loca.qty上创建唯一的复合多键索引:

db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )

如果集合中没有其他文档的索引关键字值为{ "a.loc": "B", "a.qty": null },则唯一索引允许将以下文档插入到集合中。

db.collection.insert( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )

唯一索引和缺少字段

如果文档在唯一索引中没有索引字段的值,则索引将为此文档存储一个空值。由于存在独特的约束,MongoDB 将只允许一个缺少索引字段的文档。如果有多个文档没有索引字段的值或缺少索引字段,则索引构建将失败,并出现重复的键错误。

例如,一个集合在x上具有唯一索引:

db.collection.createIndex( { "x": 1 }, { unique: true } )

如果集合尚不包含缺少字段x的文档,则唯一索引允许插入不包含字段x的文档:

db.collection.insert( { y: 1 } )

但是,如果集合中已经包含缺少字段x的文档,则在插入没有字段x的文档时,唯一索引错误:

db.collection.insert( { z: 1 } )

由于违反了对字段x的值的唯一性约束,因此该操作无法插入文档:

WriteResult({
   "nInserted" : 0,
   "writeError" : {
      "code" : 11000,
      "errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
   }
})

唯一部分索引

3.2 版中的新功能。

部分索引仅索引集合中符合指定过滤器表达式的文档。如果同时指定partialFilterExpressionunique constraint,则唯一约束仅适用于满足过滤器表达式的文档。

如果文档不符合过滤条件,则具有唯一性约束的部分索引不会阻止插入不符合唯一性约束的文档。有关示例,请参见具有唯一约束的局部索引

分片群集和唯一索引

您不能在hashed index上指定唯一约束。

对于远程分片集合,仅以下索引可以为unique

  • 分片键上的索引

  • compound index,其中分片键是prefix

  • 默认的_id索引; 然而,_id索引仅对每个分片强制执行唯一性约束 如果 _id字段不是分片键或分片键的前缀,则

Uniqueness and the _id Index

如果_id字段不是分片密钥或分片密钥的前缀,则_id索引仅对每个分片强制执行唯一性约束,而对每个分片则不强制执行约束。

例如,考虑一个跨越两个分片 A 和 B 的分片集合(具有分片键{x: 1})。由于_id键不是分片键的一部分,因此该集合可能在分片 A 中具有一个_id1的文档,而另一个文档具有分片 B 中的_id1

如果_id字段不是分片密钥也不是分片密钥的前缀,则 MongoDB 期望应用程序在分片上强制_id值的唯一性。

唯一的索引约束意味着:

  • 对于要分片的集合,如果该集合具有其他唯一索引,则无法分片该集合。

  • 对于已经分片的集合,不能在其他字段上创建唯一索引。