MongoDB支持的索引种类很多,诸如单键索引,复合索引,多键索引,TTL索引,文本索引,空间地理索引等。同时索引的属性可以具有唯一性,即唯一索引。唯一索引用于确保索引字段不存储重复的值,即强制索引字段的唯一性。缺省情况下,MongoDB的_id字段在创建集合的时候会自动创建一个唯一索引。本文主要描述唯一索引的用法。
一、创建唯一索引语法
//语法
db.collection.createIndex( <key and index type specification>, { unique: true } )
语法更多描述可参考:http://blog.csdn.net/leshami/article/details/53541978
二、演示创建唯一索引
1、演示环境
> db.version()
3.2.10
演示集合数据,可以参考:http://blog.csdn.net/leshami/article/details/52672310
> db.persons.find().limit(1).pretty()
{
"_id" : ObjectId("5812cbaaa129eed14b46458d"),
"name" : "robinson.cheng",
"age" : 25,
"email" : "robinson.cheng@qq.com",
"score" : {
"c" : 89,
"m" : 96,
"e" : 87
},
"country" : "USA",
"books" : [
"JS",
"C++",
"EXTJS",
"MONGODB"
]
}
2、单个键(列)上的唯一索引
> db.persons.createIndex({name:1},{unique:true})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
> db.persons.getIndexes()
[
{
"v" : 1,
"unique" : true, //此处表示这个索引为唯一索引
"key" : {
"name" : 1
},
"name" : "name_1",
"ns" : "test.persons"
}
]
3、基于复合键(列)的唯一索引
> db.persons.createIndex({name:1,email:1},{unique:true})
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 2,
"numIndexesAfter" : 3,
"ok" : 1
}
> db.persons.getIndexes()
[
{
"v" : 1,
"unique" : true, //此处表示这个索引为唯一索引
"key" : {
"name" : 1, //这个是索引对应的键,包括name和email
"email" : 1
},
"name" : "name_1_email_1",
"ns" : "test.persons"
}
]
4、创建唯一索引的一些限制
对于那些已经存在非唯一的列,在其上面创建唯一索引将失败
不能够基于一个哈希索引指定唯一性
Unique Constraint Across Separate Documents
唯一的约束适用于集合中的单独的文档。也就是说,唯一的索引可以防止不同的文档具有相同的索引键值,
但索引并不能阻止在基于数组或者内嵌文档创建的唯一索引上具有多个相同的值。
在一个具有重复值的单个文档的情况下,重复的值仅插入到该索引一次。
假定存在以下集合
> db.collection.insert( { a: [ { b: 4 }, { b: 4 } ] } )
WriteResult({ "nInserted" : 1 })
> db.collection.find()
{ "_id" : ObjectId("58199898ae431a4615ec75ac"), "a" : [ { "b" : 4 }, { "b" : 4 } ] }
在集合上a.b上创建一个唯一索引
> db.collection.createIndex( { "a.b": 1 }, { unique: true } )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
如果集合中没有文档上存在a.b为5的值,则唯一索引允许以下文档插入集合
> db.collection.insert( { a: [ { b: 5 }, { b: 5 } ] } )
WriteResult({ "nInserted" : 1 })
> db.collection.insert( { a: [ { b: 5 }, { b: 5 } ] } ) //再次插入则提示错误
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.collection index: a.b_1 dup key: { : 5.0 }"
}
})
> db.collection.insert( { a: [ { b: 5 }] } ) //再次插入则提示错误,即使是该文档仅有一个相同的数组元素
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.collection index: a.b_1 dup key: { : 5.0 }"
}
})
> db.collection.insert( { a: [ { b: 6 }] } )
WriteResult({ "nInserted" : 1 })
Unique Index and Missing Field
如果一个文档在一个唯一索引中没有索引字段的值,则该索引将为该文档存储一个空值。
由于唯一约束限制,MongoDB只会允许一个文档缺少索引字段。
对多于一个以上的文档没有索引字段的值或缺少索引字段,索引构建将失败,提示重复键错误。
假定存在如下集合
> db.mycol.insert({x:1})
WriteResult({ "nInserted" : 1 })
//为集合添加唯一索引
> db.mycol.createIndex( { "x": 1 }, { unique: true } )
{
"createdCollectionAutomatically" : false,
"numIndexesBefore" : 1,
"numIndexesAfter" : 2,
"ok" : 1
}
//再次插入x:1,如下,我们收到了错误提示
> db.mycol.insert({x:1})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.mycol index: x_1 dup key: { : 1.0 }"
}
})
//向集合插入文档x:2,y:2
> db.mycol.insert({x:2,y:2})
WriteResult({ "nInserted" : 1 })
//插入一个缺少x键的新文档,如下,可以成功插入
> db.mycol.insert({y:2})
WriteResult({ "nInserted" : 1 })
//再次插入一个缺少x键的新文档,提示重复
> db.mycol.insert({z:1})
WriteResult({
"nInserted" : 0,
"writeError" : {
"code" : 11000,
"errmsg" : "E11000 duplicate key error collection: test.mycol index: x_1 dup key: { : null }"
}
})
三、更多参考
MongoDB 单键(列)索引
MongoDB 复合索引
MongoDB 多键索引
MongoDB执行计划获取(db.collection.explain())