# 查询, 索引与聚合

# 1开发准备

# 1 初始化环境

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

sudo service mongodb start
1

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

mongo
1

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

# 2 初始化 MongoDB 数据库

> use Chenshi
switched to db Chenshi

> db.createCollection("shiyanlou")    #无参数
{"ok":1}

> show collections
shiyanlou
system.indexes

> userdoc1=({"user_id":1,"name":"cloud","state":"active","actor":"user","e-mail":"test@qq.com","VM_num":2,"time":[{"date":"2014-08-12","hour":"10:53 PM"}] })

> userdoc2=({"user_id":2,"name":"testadmin","state":"active","actor":"admin","e-mail":"test@qq.com","VM_num":2,"time":[{"date":"2014-08-11","hour":"06:34 AM"}] })

> doc=({"name":"peter","position":"teacher"})

> db.shiyanlou.insert(userdoc1)
WriteResult({"nInserted":1})
> db.shiyanlou.insert(userdoc2)
WriteResult({"nInserted":1})
> db.shiyanlou.insert(doc)
WriteResult({"nInserted":1})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 2 查询语句 find()

查询语句:db.COLLECTION_NAME.find(Parameter)

范例:

> db.shiyanlou.find()
1

这条指令用于查询 shiyanlou 集合中的全部文档信息,相当于 sqlite 中的 SELECT * FROM TABLE_NAME

# 1.1 条件操作符 1

MongoDB 中的条件操作符有:

  • $gt:大于
  • $lt:小于
  • $gte:大于等于
  • $lte:小于等于

范例:

> db.shiyanlou.find({user_id:{$gt:1}})
> db.shiyanlou.find({user_id:{$lte:2,$gt:1}})
1
2

# 1.2 条件操作符 2

语法:$type:[key]

可选的 key 值如下:

  • 1: 双精度型(Double)
  • 2: 字符串(String)
  • 3: 对象(Object)
  • 4: 数组(Array)
  • 5: 二进制数据(Binary data)
  • 7: 对象 ID(Object id)
  • 8: 布尔类型(Boolean)
  • 9: 日期(Date)
  • 10: 空(Null)
  • 11: 正则表达式(Regular Expression)
  • 13: JS 代码(Javascript)
  • 14: 符号(Symbol)
  • 15: 有作用域的 JS 代码(JavaScript with scope)
  • 16: 32 位整型数(32-bit integer)
  • 17: 时间戳(Timestamp)
  • 18: 64 位整型数(64-bit integer)
  • -1: 最小值(Min key)
  • 127: 最大值(Max key)

范例:

> db.shiyanlou.find({"name":{$type:2}})
1

上面的命令是用于查找 name 是字符串的文档记录,它等同于下面的命令:

> db.shiyanlou.find({"name":{$type:'string'}})
1

# 1.3 limit() 与 skip()

读取指定数量的数据记录 limit()

范例:

> db.shiyanlou.find().limit(1)
1

读取一条记录,默认是排在最前面的那一条被读取。

读取时跳过指定数量的数据记录 skip()

范例:

> db.shiyanlou.find().limit(1).skip(1)
1

当然,还可以添加 find 的查找条件的参数,以便进行更精确的查找。

# 1.4 MongoDB 排序 sort()

与 sqlite 中的排序一样有升序和降序,其中升序用 1 表示,降序用 -1 表示。

语法:db.COLLECTION_NAME.find().sort({KEY:1|-1})

范例:

> db.shiyanlou.find().sort({"time":1})
1

# 3 索引 ensureIndex()

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB 在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可能要花费几十秒甚至几分钟,这无疑对网站的性能是非常致命的。

索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库集合中一个文档或多个文档的值进行排序的一种结构。

语法:db.COLLECTION_NAME.ensureIndex({KEY:1|-1})

同样 1 代表升序,-1 代表降序。

范例:

> db.shiyanlou.ensureIndex({"name":1})
1

ensureIndex() 的可选参数:

参数 类型 描述
background Boolean 建立索引要不要阻塞其他数据库操作,默认为 false
unique Boolean 建立的索引是否唯一,默认 false
name string 索引的名称,若未指定,系统自动生成
dropDups Boolean 建立唯一索引时,是否删除重复记录,默认 flase
sparse Boolean 对文档不存在的字段数据不启用索引,默认 false
expireAfterSeconds integer 设置集合的生存时间,单位为秒
v index version 索引的版本号
weights document 索引权重值,范围为 1 到 99999
default-language string 默认为英语
language_override string 默认值为 language

范例:

> db.shiyanlou.ensureIndex({"user_id":1,"name":1},{background:1})
1

# 4 聚合 aggregate()

语法:

db.COLLECTION_NAME.aggregate({
$match:{x:1},
{limit:NUM},
$group:{_id:$age}
})
1
2
3
4
5

这些参数都可选:

  • $match:查询,跟 find 一样;
  • $limit:限制显示结果数量;
  • $skip:忽略结果数量;
  • $sort:排序;
  • $group:按照给定表达式组合结果。

范例:

> db.shiyanlou.aggregate([{$group:{_id:"$name", user:{$sum:"$user_id"}}}])
1

$name 意为取得 name 的值。

# 1 聚合表达式

名称 描述
$sum 计算总和
$avg 计算平均值
min 和min和max 计算最小值和最大值
$push 在结果文档中插入值到一个数组
$addToSet 在结果文档中插入值到一个数组,但不创建副本
$first 根据资源文档的排序获取第一个文档数据
$last 根据资源文档的排序获取最后一个文档数据

# 2 管道

MongoDB 的聚合管道将 MongoDB 文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。

表达式:处理输入文档并输出。表达式是无状态的,只能用于计算当前聚合管道的文档,不能处理其它的文档。

聚合框架中常用的几个操作:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match 使用 MongoDB 的标准查询操作。
  • $limit:用来限制 MongoDB 聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。
  • $geoNear:输出接近某一地理位置的有序文档。

范例:

> db.shiyanlou.aggregate([{$match:{user_id:{$gt:0,$lte:2}}},{$group:{_id:"user",count:{$sum:1}}}])
{"_id":"user","count":2}
1
2