美文网首页
108MongoDB 基础教程--高级查询与索引

108MongoDB 基础教程--高级查询与索引

作者: Jachin111 | 来源:发表于2021-08-24 06:54 被阅读0次

高级查询与索引

初始化环境

启动 MongoDB 服务,因为 MongoDB 并不随系统一起启动,可能以下命令运行后会等一小段的时间才会启动完毕。

sudo service mongodb start

进入 MongoDB 命令行操作界面,在命令行中敲exit可以退出。

mongo

实验中的布尔类型的 ture 用 1 代替,false 用 0 代替。

覆盖索引查询

所有的查询字段都是索引的一部分;所有的查询返回字段在同一个索引中。
由于索引存在于 RAM 中,因而从索引中获取数据要比扫描文档更快。
范例:
创建如下 users 集合(使用前面所学的方法创建该集合):

{
   "contact": "987654321",
   "dob": "01-01-1991",
   "gender": "M",
   "name": "Tom Benzamin",
   "user_name": "tombenzamin"
}

在 users 中创建一个联合索引:

> db.users.ensureIndex({gender:1,user_name:1})

该索引会覆盖下面的查询:

> db.users.find({gender:"M"},{user_name:1,_id:0})

对于上述查询,MongoDB 不会在数据库文件中查找,而会从索引中提取数据。因为索引中不包含 _id 字段,所以 _id 在查询中会默认返回,可以在查询结果中将其排除。而 db.users.find({gender:"M"},{user_name:1}) 就不会被索引覆盖。

高级索引

创建如下 users 集合(使用前面所学的方法创建该集合):

{
   "address": {
      "city": "chengdu",
      "province": "sichuan",
      "pincode": "123"
   },
   "tags": [
      "music",
      "cricket",
      "blogs"
   ],
   "name": "clound"
}

索引数组字段,在数组中创建索引,需要对数组中的每个字段依次建立索引。所以在我们为数组 tags 创建索引时,会为 music、cricket、blogs 三个值建立单独的索引。
范例:

> db.users.ensureIndex({"tags":1})

创建索引后,我们可以这样检索集合的 tags 字段:

> db.users.find({tags:"cricket"})

为了验证我们使用了索引,可以使用 explain 命令:

> db.users.find({tags:"cricket"}).explain()
image.png
索引子文档字段
假设我们需要通过 city、province、pincode 字段来检索文档,由于这些字段是子文档的字段,所以我们需要对子文档建立索引。
范例:
为子文档的三个字段创建索引,命令如下:
> db.users.ensureIndex({"address.city":1,"address.province":1,"address.pincode":1})

一旦创建索引,我们可以使用子文档的字段来检索数据:

> db.users.find({"address.city":"chengdu"})

记住查询表达式必须遵循指定的索引的顺序。所以上面创建的索引将支持以下查询:

> db.users.find({"address.city":"chengdu","address.province":"sichuan"})

同样支持以下查询:

> db.users.find({"address.city":"chengdu","address.province":"sichuan","address.pincode":"123"})

原子操作

所谓原子操作,就是要么执行成功,要么执行失败,执行成功完成既定任务,执行失败还原执行前的状态。
常用原子操作命令:
$set
用来指定一个键并更新键值,若键不存在则创建。

{ $set : { field : value } }

$unset
用来删除一个键。

{ $unset : { field : 1} }

$inc
$inc 可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。

{ $inc : { field : value } }

$push
把 value 追加到 field 里面去,field 一定要是数组类型才行,如果 field 不存在,会新增一个数组类型加进去。

{ $push : { field : value } }

$pushAll
同 $push ,只是一次可以追加多个值到一个数组字段内。

{ $pushAll : { field : value_array } }

$pull
从数组 field 内删除一个等于 value 值。

{ $pull : { field : _value } }

$addToSet
增加一个值到数组内,而且只有当这个值不在数组内才增加。
$pop
删除数组的第一个或最后一个元素。

{ $pop : { field : 1 } }

$rename
修改字段名称:

{ $rename : { old_field_name : new_field_name } }

$bit
位操作,integer 类型

{$bit : { field : {and : 5}}}

查询分析

explain()
explain() 操作提供了查询信息,使用索引及查询统计等。有利于我们对索引的优化。接下来我们在 users 集合中创建 gender 和 user_name 的索引:

> db.users.ensureIndex({gender:1,user_name:1})
> db.users.find({gender:"M"},{user_name:1,_id:0}).explain()
image.png
hint()
虽然 MongoDB 查询优化器一般工作的很不错,但是也可以使用 hints() 来强迫 MongoDB 使用一个指定的索引。通过这种方法在某些情形下会提升性能。
范例:
指定使用 gender 和 user_name 索引字段来查询:
> db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1})

可以使用 explain() 函数来分析以上查询:

> db.users.find({gender:"M"},{user_name:1,_id:0}).hint({gender:1,user_name:1}).explain()

课后习题

请通过查阅资料把 MongoDB 与一种编程语言结合使用。

挑战:管理员工的基本信息

介绍

某公司随着员工人数的增加,现需要开发一个系统用于管理员工的基本信息,请你根据给出的要求帮他们设计并实现该系统的数据库。
公司员工的信息如下:


image.png

注意服务器中的 MongoDB 服务还没有启动,需要先用 sudo service mongodb start 启动服务,然后以 mongo 命令进入 MongoDB shell 。

目标

MongoDB 服务处于运行状态;
新建的数据库名称为 shiyanlou;
在 shiyanlou 中新建集合 employee ,用于存储员工的基本信息;
将上述表中的信息插入到集合 employee 中,包括: sid,sname,age,gender,phone,address,其中 address 以嵌入式关系进行存储,包括 city,district;
员工 Tom 的电话换成了 18200753159,家从 jinniu 区 搬到了 chenghua 区,更新 Tom 的信息;
在列工号(sid)和姓名(sname)上建立索引,加快查询速度。

参考答案

创建数据库以及插入数据

$ sudo service mongodb start
$ mongo
use shiyanlou
db.employee.insert([{"sid":1001,"sname":"Tom","age":35,"gender":"male","phone":13981234567,"address":[{"city":"Chengdu","district":"jinniu"}]},{"sid":1002,"sname":"Jack","age":26,"gender":"male","phone":13981357913,"address":[{"city":"Chengdu","district":"wuhou"}]},{"sid":1003,"sname":"Rose","age":31,"gender":"female","phone":13980246802,"address":[{"city":"Chongqing","district":"jiangbei"}]},{"sid":1004,"sname":"Bob","age":29,"gender":"male","phone":13987654321,"address":[{"city":"Chongqing","district":"yuzhong"}]},{"sid":1005,"sname":"Gavin","age":24,"gender":"male","phone":13989753197,"address":[{"city":"Chengdu","district":"jinniu"}]},{"sid":1006,"sname":"Amy","age":27,"gender":"female","phone":13988642086,"address":[{"city":"Shanghai","district":"xuhui"}]},{"sid":1007,"sname":"Anne","age":23,"gender":"female","phone":18211237894,"address":[{"city":"Chengdu","district":"qingyang"}]},{"sid":1008,"sname":"John","age":33,"gender":"male","phone":18219638521,"address":[{"city":"Chongqing","district":"jiangbei"}]},{"sid":1009,"sname":"Tony","age":36,"gender":"male","phone":18211478523,"address":[{"city":"Chengdu","district":"jinniu"}]},{"sid":1010,"sname":"Betty","age":28,"gender":"female","phone":18218520369,"address":[{"city":"Beijing","district":"chaoyang"}]}])

接着上面的步骤,进行更新,导出等操作:

> db.employee.update({"sname":"Tom"},{$set:{"phone":"18200753159"}})
> db.employee.update({"sname":"Tom"},{$set:{"address.0.district":"chenghua"}})

// 如果嵌入文档未加'[]'。即不是以数组的方式,则修改子文档的命令为 db.employee.update({"sname":"Tom"},{$set:{"address.district":"chenghua"}})

> db.employee.ensureIndex({"sid":1,"sname":1})

相关文章

网友评论

      本文标题:108MongoDB 基础教程--高级查询与索引

      本文链接:https://www.haomeiwen.com/subject/pbekiltx.html