前言
上一篇介绍了 MongoDB 的索引基本操作,包括了索引查看、创建、删除,具体可以参考:MongoDB 索引操作(1)。本篇接下来介绍MongoDB索引的其他操作。
稀疏索引(Sparse Index)
稀疏索引是只对有该字段的文档建立索引,对于没有该字段的文档会当做是 null
处理。拿前面的员工举例,我们给员工增加一个手机号字段 mobile
,然后假设某些员工没有手机号且员工之间的手机号不能相同。
db.employees.update({name: 'Jenny'}, {$set: {mobile: '13800138000'}});
db.employees.update({name: '岛上码农'}, {$set: {mobile: '13800138001'}});
db.employees.update({name: 'Amy'}, {$set: {mobile: '13800138002'}});
使用的数据集如下:
{
"_id" : ObjectId("60d734f0d8079507891982a8"),
"name" : "岛上码农",
"dept" : "研发部",
"languages" : [
"Dart",
"Java",
"Javascript"
],
"age" : 30,
"totalExp" : 10,
"mobile" : "13800138001"
}
{
"_id" : ObjectId("60d734f0d8079507891982a9"),
"name" : "Amy",
"dept" : "研发部",
"languages" : [
"Java",
"Go"
],
"age" : 35,
"totalExp" : 11,
"mobile" : "13800138002"
}
{
"_id" : ObjectId("60d734f0d8079507891982aa"),
"name" : "Bob",
"dept" : "测试部",
"languages" : [
"Java",
"Javascript"
],
"age" : 36,
"totalExp" : 14
}
{
"_id" : ObjectId("60d734f0d8079507891982ab"),
"name" : "Cathy",
"dept" : "研发部",
"languages" : [
"Javascript",
"Python"
],
"age" : 31,
"totalExp" : 4
}
{
"_id" : ObjectId("60d734f0d8079507891982ac"),
"name" : "Mike",
"dept" : "测试部",
"languages" : [
"Java",
"Python",
"Go"
],
"age" : 26,
"totalExp" : 3
}
{
"_id" : ObjectId("60d734f0d8079507891982ad"),
"name" : "Jenny",
"dept" : "研发部",
"languages" : [
"Java",
"Javascipt",
"Dart"
],
"age" : 26,
"totalExp" : 3,
"mobile" : "13800138000"
}
这个时候,如果我们为了保证手机号的唯一性,直接创建手机号的唯一索引。
db.employees.createIndex({mobile: 1}, {unique: true});
这个时候会提示由于存在多个文档的 mobile
为 null
,无法保证唯一性导致创建失败。此时可以利用稀疏索引解决这个问题。
db.employees.createIndex({mobile: 1}, {unique: true, sparse: true});
通过 getIndexes
可以看到创建后的稀疏索引:
{
"v" : 2,
"unique" : true,
"key" : {
"mobile" : 1
},
"name" : "mobile_1",
"sparse" : true
}
稀疏索引相比普通索引更为紧凑,如果一个数据集只有不到10%的文档指定了该字段,可以创建更小存储空间的索引,而且占用的内存资源更小,例如下面的查询:
db.employees.find({mobile: '13800138000'});
部分索引(Partial Indexes)
部分索引意思是可以对数据集的部分满足条件的文档建立索引,而不是全部数据。下面只对超过35岁的员工建立索引(35岁对程序员是道槛,你懂的)。
db.employees.createIndex(
{age: 1},
{partialFilterExpression: {age: {$gt: 35}}}
);
获取对应的索引如下:
{
"v" : 2,
"key" : {
"age" : 1
},
"name" : "age_1",
"partialFilterExpression" : {
"age" : {
"$gt" : 35
}
}
}
对于说经常要对满足某些条件的查询来说,建立部分索引相比而言索引存储空间会更小。部分索引和稀疏索引是有不同的,稀疏索引是基于字段有没有来建立,而部分索引是基于过滤条件。而且,部分索引可以实现稀疏索引,通过判断字段是否存在的过滤条件即可完成。
db.employees.createIndex(
{mobile: 1},
{partialFilterExpression: {mobile: {$exists: true}}}
);
需要注意的是稀疏索引和部分索引对同一个字段不可同时存在。同时,当一个字段有索引时,也不可以建立部分索引。
复合索引
可以在创建索引的时候指定多个字段建立复合索引。这有点类似 SQL 的联合索引。
db.employees.createIndex({name: 1, age: -1});
需要注意的是,复合索引和联合索引类似,也存在次序的问题,当查询条件是 name
,name
和 age
的时候能够命中索引,而单独的 age
条件查询是无法使用索引的。同样的对于排序来说,也是需要匹配建立索引的次序。
独立索引
独立索引在创建索引的属性增加{unique: true}
即可。
db.employees.createIndex({name: 1}, {unique: true});
如果数据集存在相同属性的字段时,建立索引会失败,包括未指定该字段的文档超过2个以上时。
总结
可以看到,MongoDB 的索引除了具备 SQL 常见的索引外,还支持了稀疏索引和部分索引,这应该也是 MongoDB 改进了关系型数据库的一些缺陷得到的改进。实际应用中可以根据需要来选择如何使用索引。
网友评论