唯一索引可确保索引字段不存储重复值,并且一个值对于给定字段最多出现一次。唯一复合索引可确保索引键值的任何给定组合最多出现一次。默认下, MongoDB在创建集合期间在_id字段上创建唯一索引。
创建唯一索引
要创建唯一索引,请使用 db.collection.createIndex() 方法,并将 unique 选项设置为 true。
db.collection.createIndex( <key and index type specification>, { unique: true } )单个字段上的唯一索引
例如,要对 users 集合的 email 字段创建唯一索引,请在 mongosh 中使用以下操作:
db.users.createIndex( { "email": 1 }, { unique: true } )唯一符合索引
您还可以对复合索引的索引键值组合实施唯一约束。
例如,要在 users 集合的 name、email 和 password 字段上创建唯一索引,请在 mongosh 中使用以下操作:
db.users.createIndex( { name: 1, email: 1, password: 1 }, { unique: true } )在 email 和 name 上创建唯一的复合多键索引:
db.users.createIndex( { "email": 1, "name": 1 }, { unique: true } )唯一索引允许将以下文档插入集合,因为该索引强制 email 和 name 值的组合有唯一性:
db.users.insertMany( [ { name: "Catelyn Stark", email: [ "catelyn@gameofthron.es", "sean_bean@gameofthron.es" ], password: "$2b$12$hash2" }, { name: "Arya Stark", email: [ "catelyn@gameofthron.es" ], password: "$2b$12$hash3" }] )即使两个文档的 email 数组中都有 "catelyn@gameofthron.es",操作仍会成功,因为每个电子邮件值与 name 字段的组合都是唯一的。
行为
限制
如果集合中已经包含会违反索引唯一性约束的数据,则 MongoDB 无法在指定的索引字段上创建唯一索引。
要将现有的非唯一索引转换为唯一索引,请参阅将现有索引转换为唯一索引。
不能在哈希索引上指定唯一约束。
在副本集和分片集群上构建唯一索引
对于副本集和分片集群,使用滚动过程创建唯一索引要求您在该过程中停止对集合的所有写入。如果在此过程中无法停止对集合的所有写入,请勿使用滚动过程。相反,要为集合构建唯一索引,您必须执行以下操作之一:
在副本集的主节点上运行
db.collection.createIndex()。在
mongos上为分片集群运行db.collection.createIndex()
跨单独文档的唯一性约束
唯一索引可防止集合中的不同document具有相同的索引键值。
由于该约束适用于独立文档,因此对于唯一多键索引,只要某文档的索引键值与其他文档的索引键值不重复,该文档就可能包含导致重复索引键值的数组元素。在这种情况下,重复的索引条目仅插入索引一次。
示例,在 email 和 name 上创建唯一复合多键索引:
db.users.createIndex( { "email": 1, "name": 1 }, { unique: true } )如果此集合中没有其他文档的索引键值为 { "email": "arya@winterfell.com", "name": null },则该唯一索引允许将以下文档插入集合:
db.users.insertOne( { _id: ObjectId("59b99db4cfa9a34dcd7885b9"), email: [ "arya@winterfell.com", "arya@gameofthron.es" ] } )唯一单字段索引中缺失文档字段
对于唯一单字段索引中的索引字段,如果某文档存在 null 或缺失值,则该索引为该文档存储 null 值。由于唯一性约束,单字段唯一索引只能包含一份文档,且该文档在其索引条目中包含 null 值。如果索引条目中存在多份具有 null 值的文档,则索引构建会失败并出现重复键错误。
例如,集合在 email 上具有唯一单字段索引:
db.users.createIndex( { "email": 1 }, { unique: true } )如果集合尚不包含缺少 email字段的document,则唯一索引允许插入没有 email字段的document:
db.users.insertOne( { name: "Arya Stark" } )但是,如果集合已包含缺少 email字段的document,则无法插入没有 email字段的第二个document。尝试插入另一个不带 email字段的 document 的第二个操作无法插入该 document,因为违反了 email字段的唯一约束条件。
唯一部分索引
如果同时使用 partialFilterExpression 和唯一约束,则唯一约束仅应用于符合过滤器表达式的document。有关示例,请参阅具有唯一约束的部分索引。
分片集群和唯一索引
稀疏和非稀疏唯一索引
从 MongoDB 5.0 开始,具有相同键模式的唯一稀疏和唯一非稀疏索引可以存在于同一个集合中。
唯一和稀疏索引创建
此示例将使用相同的键模式和不同的 sparse 选项来创建多个索引:
db.users.createIndex( { password : 1 }, { name: "unique_index", unique: true } )db.users.createIndex( { password : 1 }, { name: "unique_sparse_index", unique: true, sparse: true } )基本索引和稀疏索引创建
还可以使用和不使用稀疏选项创建具有相同键模式的基本索引:
db.users.createIndex( { password : 1 }, { name: "sparse_index", sparse: true } )db.users.createIndex( { password : 1 }, { name: "basic_index" } )具有重复键模式的基本索引和唯一索引
基本索引和唯一索引可以使用相同的键模式。
示例,您可以创建以下两个使用相同键模式的索引:
db.users.createIndex( { email : 1 }, { name: "basic_index" } )db.users.createIndex( { email : 1 }, { name: "unique_index", unique: true } )