Loading...
墨滴

岛上码农@公众号同名

2021/09/01  阅读:18  主题:默认主题

MongoDB 索引操作(下)

前言

上一篇介绍了 MongoDB 的索引基本操作,包括了索引查看、创建、删除,具体可以参考。这一篇接下来介绍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});

这个时候会提示由于存在多个文档的 mobilenull,无法保证唯一性导致创建失败。此时可以利用稀疏索引解决这个问题。

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});

需要注意的是,复合索引和联合索引类似,也存在次序的问题,当查询条件是 namenameage 的时候能够命中索引,而单独的 age 条件查询是无法使用索引的。同样的对于排序来说,也是需要匹配建立索引的次序。

独立索引

独立索引在创建索引的属性增加{unique: true}即可。

db.employees.createIndex({name: 1}, {unique: true});

如果数据集存在相同属性的字段时,建立索引会失败,包括未指定该字段的文档超过2个以上时。

总结

可以看到,MongoDB 的索引除了具备 SQL 常见的索引外,还支持了稀疏索引和部分索引,这应该也是 MongoDB 改进了关系型数据库的一些缺陷得到的改进。实际应用中可以根据需要来选择如何使用索引。 关注岛上码农

岛上码农@公众号同名

2021/09/01  阅读:18  主题:默认主题

作者介绍

岛上码农@公众号同名