Unique Indexes唯一索引
On this page本页内容
A unique index ensures that the indexed fields do not store duplicate values; i.e. enforces uniqueness for the indexed fields. 唯一索引可确保索引字段不会存储重复的值;即强制索引字段的唯一性。By default, MongoDB creates a unique index on the _id field during the creation of a collection.默认情况下,MongoDB在创建集合的过程中会在_id
字段上创建一个唯一的索引。
New Internal Format新内部格式
Starting in MongoDB 4.2, for featureCompatibilityVersion (fCV) of 4.2 (or greater), MongoDB uses a new internal format for unique indexes that is incompatible with earlier MongoDB versions. 从MongoDB 4.2开始,对于4.2(或更高版本)的featureCompatibilityVersion
(fCV),MongoDB为唯一索引使用了一种新的内部格式,这与早期的MongoDB版本不兼容。The new format applies to both existing unique indexes as well as newly created/rebuilt unique indexes.新格式既适用于现有的唯一索引,也适用于新创建/重建的唯一索引。
Create a Unique Index创建唯一索引
To create a unique index, use the 若要创建唯一索引,请使用db.collection.createIndex()
method with the unique
option set to true
.db.collection.createIndex()
方法,并将unique
选项设置为true
。
db.collection.createIndex( <key and index type specification>, { unique: true } )
Unique Index on a Single Field单个字段上的唯一索引
For example, to create a unique index on the 例如,要在user_id
field of the members
collection, use the following operation in mongosh
:members
集合的user_id
字段上创建唯一索引,请在mongosh
中使用以下操作:
db.members.createIndex( { "user_id": 1 }, { unique: true } )
Unique Compound Index唯一复合索引
You can also enforce a unique constraint on compound indexes. 还可以对复合索引强制执行唯一约束。If you use the unique constraint on a compound index, then MongoDB will enforce uniqueness on the combination of the index key values.如果对复合索引使用唯一约束,那么MongoDB将对索引键值的组合强制执行唯一性。
For example, to create a unique index on 例如,要在成员集合的groupNumber
, lastname
, and firstname
fields of the members
collection, use the following operation in mongosh
:groupNumber
、lastname
和firstname
字段上创建唯一索引,请在mongosh
中使用以下操作:
db.members.createIndex( { groupNumber: 1, lastname: 1, firstname: 1 }, { unique: true } )
The created index enforces uniqueness for the combination of 创建的索引强制groupNumber
, lastname
, and firstname
values.groupNumber
、lastname
和firstname
值的组合具有唯一性。
For another example, consider a collection with the following document:例如,考虑一个包含以下文档的集合:
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
Create a unique compound multikey index on 在a.loc
and a.qty
:a.loc
和a.qty
上创建一个唯一的复合多键索引:
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
The unique index permits the insertion of the following documents into the collection since the index enforces uniqueness for the combination of 唯一索引允许在集合中插入以下文档,因为索引强制a.loc
and a.qty
values:a.loc
和a.qty
值的组合具有唯一性:
db.collection.insertMany( [
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] },
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }
] )
Behavior行为
Restrictions限制
MongoDB cannot create a unique index on the specified index field(s) if the collection already contains data that would violate the unique constraint for the index.如果集合中已经包含违反索引唯一约束的数据,MongoDB就无法在指定的索引字段上创建唯一索引。
You may not specify a unique constraint on a hashed index.您不能在哈希索引上指定唯一约束。
Building Unique Index on Replica Sets and Sharded Clusters在副本集和分片群集上建立唯一索引
For replica sets and sharded clusters, using a rolling procedure to create a unique index requires that you stop all writes to the collection during the procedure. 对于副本集和分片集群,使用滚动过程创建唯一索引需要在该过程中停止对集合的所有写入。If you cannot stop all writes to the collection during the procedure, do not use the rolling procedure. 如果在该过程中无法停止对集合的所有写入,请不要使用滚动过程。Instead, build your unique index on the collection by:相反,可以通过以下方式在集合上建立您的唯一索引:
issuing在副本集的主服务器上发出db.collection.createIndex()
on the primary for a replica set, ordb.collection.createIndex()
,或者issuing在db.collection.createIndex()
on themongos
for a sharded cluster.mongos
上为分片集群发出db.collection.createIndex()
。
Unique Constraint Across Separate Documents跨单独文档的唯一约束
The unique constraint applies to separate documents in the collection. 唯一约束适用于集合中的单独文档。That is, the unique index prevents separate documents from having the same value for the indexed key.也就是说,唯一索引防止单独的文档具有相同的索引键值。
Because the constraint applies to separate documents, for a unique multikey index, a document may have array elements that result in repeating index key values as long as the index key values for that document do not duplicate those of another document. 由于该约束适用于单独的文档,因此对于唯一的多键索引,只要该文档的索引键值不与另一文档的索引键值重复,则该文档可能具有导致重复索引键值的数组元素。In this case, the repeated index entry is inserted into the index only once.在这种情况下,重复的索引条目只插入索引一次。
For example, consider a collection with the following documents:例如,考虑一个包含以下文档的集合:
{ _id: 1, a: [ { loc: "A", qty: 5 }, { qty: 10 } ] }
{ _id: 2, a: [ { loc: "A" }, { qty: 5 } ] }
{ _id: 3, a: [ { loc: "A", qty: 10 } ] }
Create a unique compound multikey index on 在a.loc
and a.qty
:a.loc
和a.qty
上创建一个唯一的复合多键索引:
db.collection.createIndex( { "a.loc": 1, "a.qty": 1 }, { unique: true } )
The unique index permits the insertion of the following document into the collection if no other document in the collection has an index key value of 如果集合中没有其他文档的索引键值为{ "a.loc": "B", "a.qty": null }
.{ "a.loc": "B", "a.qty": null }
,则唯一索引允许将以下文档插入到集合中。
db.collection.insertOne( { _id: 4, a: [ { loc: "B" }, { loc: "B" } ] } )
Unique Index and Missing Field唯一索引和缺少字段
If a document does not have a value for the indexed field in a unique index, the index will store a null value for this document. 如果文档在唯一索引中没有索引字段的值,则索引将为此文档存储一个空值。Because of the unique constraint, MongoDB will only permit one document that lacks the indexed field. 由于唯一的限制,MongoDB将只允许一个缺少索引字段的文档。If there is more than one document without a value for the indexed field or is missing the indexed field, the index build will fail with a duplicate key error.如果有多个文档没有索引字段的值或缺少索引字段,则索引生成将失败,并出现重复键错误。
For example, a collection has a unique index on 例如,集合在x
:x
上具有唯一索引:
db.collection.createIndex( { "x": 1 }, { unique: true } )
The unique index allows the insertion of a document without the field 如果集合中尚未包含缺少字段x
if the collection does not already contain a document missing the field x
:x
的文档,则唯一索引允许插入没有字段x
的文件:
db.collection.insertOne( { y: 1 } )
However, the unique index errors on the insertion of a document without the field 但是,如果集合中已经包含缺少字段x
if the collection already contains a document missing the field x
:x
的文档,则在插入没有字段x
的文件时会出现唯一索引错误:
db.collection.insertOne( { z: 1 } )
The operation fails to insert the document because of the violation of the unique constraint on the value of the field 由于违反了对字段x
:x
值的唯一约束,操作无法插入文档:
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error index: test.collection.$a.b_1 dup key: { : null }"
}
})
See also: 另请参阅:
Unique Partial Indexes唯一部分索引
Partial indexes only index the documents in a collection that meet a specified filter expression. 分部索引仅对集合中符合指定筛选表达式的文档进行索引。If you specify both the 如果同时指定partialFilterExpression
and a unique constraint, the unique constraint only applies to the documents that meet the filter expression.partialFilterExpression
和唯一约束,则唯一约束仅适用于满足筛选表达式的文档。
A partial index with a unique constraint does not prevent the insertion of documents that do not meet the unique constraint if the documents do not meet the filter criteria. 如果文档不符合筛选条件,则具有唯一约束的部分索引不会阻止插入不符合唯一约束的文档。For an example, see Partial Index with Unique Constraint.有关示例,请参阅具有唯一约束的部分索引。
Sharded Clusters and Unique Indexes分片群集和唯一索引
You cannot specify a unique constraint on a hashed index.不能对哈希索引指定唯一约束。
For a ranged sharded collection, only the following indexes can be unique:对于范围内的分片集合,只有以下索引可以是唯一的:
the index on the shard key分片键上的索引a compound index where the shard key is a prefix分片键是前缀的复合索引the default默认的_id
index; however, the_id
index only enforces the uniqueness constraint per shard if the_id
field is not the shard key or the prefix of the shard key._id
索引;然而,如果_id
字段不是分片键或分片键的前缀,则_id
索引仅强制每个分片的唯一性约束。ImportantUniqueness and the _id Index唯一性和_id
索引If the如果_id
field is not the shard key or the prefix of the shard key,_id
index only enforces the uniqueness constraint per shard and not across shards._id
字段不是分片键或分片键的前缀,那么_id
索引只强制每个分片的唯一性约束,而不强制跨分片的惟一性约束。For example, consider a sharded collection (with shard key例如,考虑一个跨越两个分片a和B的分片集合(具有分片键{x: 1}
) that spans two shards A and B.{x: 1}
)。Because the因为_id
key is not part of the shard key, the collection could have a document with_id
value1
in shard A and another document with_id
value1
in shard B._id
键不是分片键的一部分,所以集合可能在分片A中有一个_id
值为1
的文档,而在分片B中有另一个_id
值为1
。If the如果_id
field is not the shard key nor the prefix of the shard key, MongoDB expects applications to enforce the uniqueness of the_id
values across the shards._id
字段既不是分片键,也不是分片键的前缀,MongoDB希望应用程序在分片之间强制执行_id
值的唯一性。
The unique index constraints mean that:唯一的索引约束意味着:
For a to-be-sharded collection, you cannot shard the collection if the collection has other unique indexes.对于要分片的集合,如果该集合具有其他唯一索引,则不能对该集合进行分片。For an already-sharded collection, you cannot create unique indexes on other fields.对于已经分片的集合,不能在其他字段上创建唯一索引。
Sparse and Non-Sparse Unique Indexes稀疏和非稀疏唯一索引
Starting in MongoDB 5.0, unique sparse and unique non-sparse indexes with the same key pattern can exist on a single collection.从MongoDB 5.0开始,具有相同键模式的唯一稀疏索引和唯一非稀疏索引可以存在于单个集合中。
Unique and Sparse Index Creation创建独特且稀疏的索引
This example creates multiple indexes with the same key pattern and different 此示例使用相同的键模式和不同的sparse
options:sparse
选项创建多个索引:
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )
Basic and Sparse Index Creation基本和稀疏索引创建
You can also create basic indexes with the same key pattern with and without the sparse option:您还可以创建具有相同键模式的基本索引,可以使用稀疏选项,也可以不使用稀疏选项:
db.scoreHistory.createIndex( { score : 1 }, { name: "sparse_index", sparse: true } )
db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )
Basic and Unique Indexes With Duplicate Key Patterns具有重复键模式的基本索引和唯一索引
Starting in MongoDB 5.0, basic and unique indexes can exist with the same key pattern.从MongoDB 5.0开始,基本索引和唯一索引可以使用相同的键模式存在。
This duplication in key patterns allows for adding a unique index to already indexed fields.键模式中的这种重复允许向已编制索引的字段添加唯一索引。
In this example:在本例中:
Create a basic index with the key pattern 使用键模式{ score : 1 }
and insert three documents.{ score : 1 }
创建一个基本索引,并插入三个文档。
db.scoreHistory.createIndex( { score : 1 }, { name: "basic_index" } )
db.scoreHistory.insert( { score : 1 } )
db.scoreHistory.insert( { score : 2 } )
db.scoreHistory.insert( { score : 3 } )
Create a unique index with the same key pattern 使用相同的键模式{ score : 1 }
.{ score : 1 }
创建唯一索引。
db.scoreHistory.createIndex( { score : 1 }, { name: "unique_index", unique: true } )
Try to insert a duplicate 尝试插入由于唯一索引而失败的重复score
document that fails because of the unique index.score
文档。
db.scoreHistory.insert( { score : 3 } )