MongoDB
一、 MongoDB 简介
1 什么是 MongoDB
MongoDB 是一个基于分布式文件存储的数据库。由 C++语言编写。在为 WEB 应用提供可扩展的高性能数据存储解决方案。MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似 json 的 bson 格式,因此可以存储比较复杂的数据类型。Mongo 最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。
2 什么是 NoSQL
NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是 SQL”,是一项全新的数据库革命性运动,早期就有人提出,发展至 2009 年趋势越发高涨。NoSQL 的拥护者们提倡运用非关系型的数据存储,相对于铺天盖地的关系型数据库运用,这一概念无疑是一种全新的思维的注入。
3 NoSQL 数据库的分类
3.1 键值(Key-Value) 存储数据库
这一类数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据。Key/value 模型对于 IT 系统来说的优势在于简单、易部署。但是如果 DBA 只对部分值进行查询或更新的时候,Key/value 就显得效率低下了。例如: Redis
3.2 列存储数据库
这部分数据库通常是用来应对分布式存储的海量数据。键仍然存在,但是它们的特点是指向了多个列。这些列是由列家族来安排的。如:HBase。
3.3 文档型数据库
文档型数据库的灵感是来自于 Lotus Notes 办公软件的,而且它同第一种键值存储相类似。该类型的数据模型是版本化的文档,半结构化的文档以特定的格式存储,比如 JSON。文档型数据库可 以看作是键值数据库的升级版,允许之间嵌套键值。而且文档型数据库比键值数据库的查询效率更高。如:CouchDB, MongoDB. 国内也有文档型数据库 SequoiaDB,已经开源。
3.4 图形(Graph) 数据库
图形结构的数据库同其他行列以及刚性结构的 SQL 数据库不同,它是使用灵活的图形模型,并且能够扩展到多个服务器上。NoSQL 数据库没有标准的查询语言(SQL),因此进行数据库查询需要制定数据模型。许多 NoSQL 数据库都有 REST 式的数据接口或者查询 API。
如:Neo4J, InfoGrid。
二、 MongoDB 与关系型数据库对比
1 与关系型数据库术语对比
2 储存数据对比
3 RDBMS 与 MongoDB 对应的术语
三、 MongoDB 的数据类型
字符串类型数据的编码格式必须是UTF-8
四、 MongoDB 的下载与安装
1 下载 MongoDB
下载地址:https://www.mongodb.com/download-center/community
2 安装 MongoDB
2.1.1 下载 ForLinux 平台的 MongoDB
2.2 Linux 安装
在 Linux 平台的 MongoDB 为解压版。我们只要解压 tgz 文件就可以使用。
2.2.1 将下载的 tgz 包上传到 Linux 环境中
我将 tgz 包上传到了自己创建的 temp 目录中。该目录位于/root 目录中。
2.2.2 解压 tgz 文件
通过 tar 命令对 tgz 文件做解压处理。
2.2.3 移动 MongoDB
我们将解压完的 MongoDB 目录移动到/usr/local 目录中并改名为 mongodb。
2.2.4 创建数据库目录
***MongoDB 的数据存储在 data 目录的 db 目录下,但是这个目录在安装过程不会自动创建,需要手动创建 data 目录,并在 data 目录中创建 db 目录。data 目录可以创建在任何位置。***本套视频中,我们将 data 目录创建在 mongodb 的根目录下。
至此 Linux 平台中的 MongoDB 就已经安装完毕。
3 MongoDB 的启动与关闭
3.1 启动 MongoDB
MongoDB 的启动方式分为两种
1)前置启动
2)后置启动
无论哪种启动方式都需要执行 bin 目录中的 mongod 命令。
MongoDB 在启动时默认的查找数据库的路径为/data/db(在Linux的根下)。
如果我们数据库路径有变化,需要在该命令中通过–dbpath 参数来指定 db 目录的路径(该路径可以是绝对路径,也可是相对路径)。
3.1.1 前置启动
MongoDB 的默认启动方式为前置启动。所谓前置启动就是 MongoDB 启动进程后会占用当前终端窗口。
进入到 MongoDB 的 bin 目录。
执行 bin 目录中的 mongod 命令。
由于我们的 db 目录放在 mongodb 的根下,所以在执行该命令时需要通过 --dbpath 参数指定 db 路径。
启动后会在终端中输出一些启动信息。此时终端窗口已被启动进程所占用。我们通过启动信息可以看到 MongoDB 默认的监听端口为 27017
已启动
按 Ctrl+C 可结束启动进程关闭 MongoDB
3.1.2 后置启动
所谓后置启动就是以守护进程的方式启动 MongoDB。我们需要在执行 mongod 命令中添加 --fork 参数。需要注意的是,–fork 参数需要配合着–logpath 或者是–syslog 参数使用。
–logpath 与–syslog 参数是指定 MongoDB 的日志文件。MongoDB 的日志文件可以在系统中的任意位置,
本视频中我们在 mongodb 目录下创建 log 目录,在该目录中创建一个名为mongodb.log 的日志文件。
创建 log 目录
在 log 目录中创建 mongodb.log 日志文件
后置启动 MongoDB
3.1.3 常见的启动参数
3.1.4 通过配置文件加载启动参数
如果觉得在启动 MongoDB 时给定的参数项太多,那么我们也可以通过配置文件来配置启动参数,配置文件可以在任意目录中,配置文件的扩展名应为.conf,配置文件中使用key=value 结构。在执行 MongoDB 时通过–config 参数来指定需要加载的配置文件。我们在 mongodb 目录下创建一个 etc 目录,在该目录中创建一个名为 mongodb.conf 的配置文件。
bind_ip=0.0.0.0 表示允许任何主机连接
关闭MongoDB
通过编写的配置文件启动MongoDB
3.1.5 配置环境变量
为了能够在任何目录中执行 bin 目录中的命令,我们可以将 bin 目录添加到环境变量中。
修 改 /etc/profile 文 件 , 添 加 export PATH=/usr/local/mongodb/bin:$PATH 。
/usr/local/mongodb/bin 为 MongoDB 的 bin 目录的绝对路径。同学们可根据自己的情况来指定。
重新加载配置文件
测试结果
修改了配置文件之后,可以在任何目录下连接MongoDB
3.2 关闭 MongoDB
3.2.1 使用 Ctrl+C 关闭
如果我们的启动方式是前置启动,那么直接使用快捷键 Ctrl+C 就可以关闭 MongoDB。
这种关闭方式会等待当前进行中的的操作完成,所以依然是安全的关闭方式。
3.2.2 使用 kill 命令关闭
我们可以通过 Linux 的 kill 命令结束 MongoDB 进程,然后删除 data/db 目录中的mongod.lock 文件,否则下次无法启动。但是此方法不建议使用,因为会造成数据损坏现象。
3.2.3 使用 MongoDB 的函数关闭
在 MongoDB 中提供了两个关闭数据库的函数:
db.shutdownServer()
db.runCommand(“shutdown”)
如上两个方法都需要在 admin 库中执行,并且都是安全的关闭方式。
Ctrl+C 退出客户端工具
MongoDB已经关闭了
3.2.4 使用 mongod 命令关闭 MongoDB
mongod --shutdown --dbpath<数据库路径>
mongod 命令的 shutdown 选项能安全的关闭 MongoDB 服务
先启动MongoDB
关闭MongoDB
在这个配置文件里要的仅仅是 /usr/local/mongodb/data/db 指定数据库位置即可
五、 MongoDB 的用户与权限管理
Mongodb 作为时下最为热门的数据库,那么其安全验证也是必不可少的,否则一个没有验证的数据库暴露出去,任何人可随意操作,这将是非常危险的。我们可以通过创建用户的方式来降低风险。
1 Mongodb 用户权限列表
2 MongoDB 用户使用
2.1 创建 DB 管理用户
mongodb 有一个用户管理机制,简单描述为,有一个管理用户组,这个组的用户是专门为管理普通用户而设的,暂且称之为管理员。
管理员通常没有数据库的读写权限,只有操作用户的权限, 因此我们只需要赋予管理员userAdminAnyDatabase 角色即可。
另外管理员账户必须在 admin 数据库下创建。
2.1.1 切换到 Admin 库
管理员需要在 admin 数据库下创建,所以我们需要切换到 admin 数据库。
2.1.2 查看 admin 中的用户
我们可以通过 db.system.users.find()函数来查看 admin 库中的所有用户信息。
目前在 admin 库中没有用户,所以查无结果。
2.1.3 db.createUser 函数
在 MongoDB 中可以使用 db.createUser({用户信息})函数创建用户
1)user:新建用户名。
2)pwd:新建用户密码。
3)customData:存放一些用户相关的自定义数据,该属性也可忽略。
4)roles:数组类型,配置用户的权限。
2.1.4 创建管理员用户
我们现在需要在 admin 库中创建一个名为 bjsxt 的管理员用户,密码为 bjsxt
db.createUser({user:‘bjsxt’,pwd:‘bjsxt’,roles:[{role:‘userAdminAnyDatabase’,db:‘admin’}])
创建成功后会看到如下提示:
2.1.5 重启 MongoDB
在管理员账户创建完成后,我们需要重新启动 MongoDB,并开启验证。
重新启动函数:db.shutdownServer()。
查询到用户 bjsxt
2.1.6 使用权限方式启动 MongoDB
***在默认的情况下 MongoDB 是不开启用户认证的。***如果我们添加用户,那么需要开启用户认证机制。通过修改 mongodb.conf 配置文件,在文件中添加 auth=true 即可。
先停掉MongoDB再编辑配置文件
修改完成后启动 MongoDB。
2.1.7 用户认证
创建管理员后,需要认证方可使用该用户,否则会提示需要认证。
认证函数:db.auth(‘用户名’,’密码’)
如果结果返回 1,则表示认证成功,返回 0 则表示认证失败。
登录成功后可查询用户
2.2 创建普通用户
普通用户由管理员创建。通常需要指定操作某个数据库。
2.2.1 需求
我们创建一个 sxt 数据库,给这个数据库添加一个用户,用户名为 itsxt,密码为 itsxtpwd。
并授予该用户对 sxt 数据库进行读写操作的权限。
2.2.2 使用管理员用户登录
普通用户需要由管理员创建并授权。所以,我们首先做的就是用管理员账户登录数据库。
2.2.3 创建 sxt 数据库
use 命令切换数据库时如果该库不存在,那么则会创建该数据库。
2.2.4 创建普通用户
给定字符串可以用单引号也可以用双引号
2.2.5 使用普通用户
打开一个新的客户端。
2.2.6 切换到 sxt 数据库
由于我们是在 sxt 数据库中创建的 itsxt 用户,所以需要先切换到 sxt 库。
错误原因没有认证 一旦开启MongoDB的认证之后操作MongoDB必须认证
2.2.7 登录普通用户
如果我们不登录会发现无法对该数据库进行插入操作。因为缺少用户认证。
通过认证函数对用户进行登录认证。
认证成功后操作通过该用户操作 sxt 库。该用户对 sxt 库具备读写操作。
成功插入
查看出入的数据
2.3 更新用户角色
如果我们需要对已存在的用户的角色做修改,那么我们可以使用 db.updateUser()函数来更新用户角色。注意,该函数需要当前用户具有 userAdminAnyDatabase 或者更高的权限。
2.3.1 更新角色语法格式
db.updateUser(“用户名”, {“roles”:[{“role”:“角色名称”},{“更新项 2”:“更新内容”}]})
2.3.2 需求
目前 bjsxt 管理员用户只具备 userAdminAnyDatabase 用户管理角色,我们为该用户添加
一个 dbAdminAnyDatabase 数据库管理角色。
2.3.3 更新角色
db.updateUser(“bjsxt”,{roles : [{“role” : “userAdminAnyDatabase”,“db” : “admin”},{“role” :
“dbAdminAnyDatabase”,“db” : “admin”}]})
如果没有提示任何信息则表示更新成功。退出当前客户端重新连接即可生效。
被更新的用户在哪个数据库下创建的更新时必须切换到哪个数据库下,然后再做角色更新
2.3.4 查看用户信息
通过 show users 命令查看到 bjsxt 用户的角色已经发生改变。
2.4 更新用户密码
更新用户密码有两种方式:
1)使用 db.updateUser()函数更新密码。 不仅仅是更新用户密码
2)使用 db.changeUserPassword()函数更新密码 只能更新用户密码
2.4.1 更新密码方式一
使用 db.upateUser()函数将 bjsxt 用户的密码修改为 sxt
必须切换到用户创建时所指定的数据库才能更新
2.4.1.1 语法格式
db.updateUser(“用户名”,{“pwd”:“新密码”})
如果未提示任何信息则表示更新成功。退出当前客户端重新连接认证即可。
重新使用 bjsxt 用户登录
2.4.2 更新密码方式二
使用 db.changeUserPassword()函数将 bjsxt 用户的密码修改为 bjsxt。
2.4.2.1 语法格式
db.changeUserPassword(“用户名”,“新密码”)
如果未提示任何信息则表示更新成功。退出当前客户端重新连接认证即可。
重新使用 bjsxt 用户登录
2.5 删除用户
通过 db.dropUser()函数可删除指定用户。删除成功后会返回 true。
在删除用户时需要切换到创建用户时所指定的数据库中才可以删除。
注意:需要使用具有 userAdminAnyDatabse角色管理员用户才可以删除其他用户。
2.5.1 需求
我们使用 db.dropUser()函数将 itsxt 用户删除。
2.5.2 切换数据库
itsxt 用户在 sxt 数据库中,所以需要先切换到 sxt 数据库。
2.5.3 通过函数删除用户
我们可以看到,该函数返回了 true,表示删除成功。
六、 MongoDB 的数据库操作
1 创建数据库
在 MongoDB 中创建数据库的命令使用的是 use 命令。该命令有两层含义:
1)切换到指定数据库。
2)如果切换的数据库不存在,则创建该数据库。
我们使用 use 命令创建一个名为 sxttest 的数据库。
在没有用户认证的情况下也可以创建数据库
2 查看 所有数据库
我们可以通过 show dbs 命令查看当前 MongoDB 中的所有数据库。
如果开启了用户认证,则需要先登录方可查看到结果,否则不显示任何信息。
如果使用的是具备数据库管理员角色的用户,那么则可以看到 MongoDB 中的所有数据库,
如果使用的普通用户登录的那么只能查询到该用户所拥有的数据库。
用户未登录查询数据库。
使用具有数据库管理员角色的用户登录查询数据库。
在查询结果中并未包含我们刚刚创建的 sxttest 数据库。因为,在 show dbs 命令中不显示未含有任何信息的数据的库。(只显示使用过的数据库)
使用普通用户登录查询数据库。
创建一个普通用户 itsxt
itsxt 用户是在admin 库下创建的,所以得在admin 库下登录
我们在 sxt 数据库中创建一个只具备读写权限的普通用户。
使用普通用户登录并查询数据库。
3 删除数据库
在 MongoDB 中使用 db.dropDatabase()函数来删除数据库。
在删除数据库之前,需要使用具备 dbAdminAnyDatabase 角色的管理员用户登录,然后切换到需要删除的数据库,执行db.dropDatabase()函数即可。删除成功后会返回一个{ “ok” : 1 }的 JSON 字符串。
我们现在将刚刚创建的 sxttest 删除。
七、 MongoDB 的集合操作
MongoDB 中的集合是一组文档的集,相当于关系型数据库中的表。
1 创建集合
MongoDB 使用 db.createCollection()函数来创建集合。
语法格式:db.createCollection(name, options)。
name: 要创建的集合名称。
options: 可选参数, 指定有关内存大小及索引的选项。
options 可以是如下参数。
在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。
1.1 使用默认集合
在 MongoDB 中,我们也可以不用创建集合,当我们插入一些数据时,会自动创建集合,并且会使用数据库的名字作为集合的名称。
创建一个新数据库,名为 develop
如果开启认证,需要为新数据库创建访问用户。新建用户名为 itsxt,密码为 itsxt
先使用有创建用户权限的用户进行认证,再切换到指定的库里创建用户
使用 itsxt 用户登录 develop 库
复制一个终端窗口
向 develop 库中插入一条数据
如果不创建用户默认会自动创建一个与数据库同名的集合
查询集合
1.2 创建不带参数的集合
我们也可以根据自己的情况创建集合。在 develop 数据库中创建一个名为 dev 的集合,该集合创建时不指定任何参数。如果开启认证,则需要使用具有数据库管理员权限的用户来创建集合。
只给定一个参数就是集合的名字
1.3 创建带参数的集合
在 develop 数据库中创建一个名为 dev2 的固定集合,整个集合空间大小为 2000000kb,文档最大个数为 1000。
2 查看集合
如果要查看已有集合,可以使用 show collections 或 show tables 命令。
2.1 show collections
2.2 show tables
3 删除集合
如果我们要删除集合,需要先切换到需要删除集合所在的数据库,使用 drop()函数删除集合即可。
删除集合的语法格式为:db.集合名称.drop()。
删除 dev2 集合
八、 MongoDB 的文档操作
在 MongoDB 中文档是指多个键及其关联的值有序地放置在一起就是文档,其实指的就是数据,也是我们平时操作最多的部分。
MongoDB 中的文档的数据结构和 JSON 基本一样。所有存储在集合中的数据都是
BSON 格式。
BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。
1 插入文档
1.1 插入单个文档
1.1.1 insert 函数
语法格式为:db.COLLECTION_NAME.insert(document)。
向 dev 集合中插入单个文档。
{title:‘北京尚学堂’,description:‘程序员的摇篮’,url:‘www.bjsxt.com’,tags:[‘java’,‘大数据’,‘python’]}
查看文档
用itsxt 用户进行插入数据
1.1.2 save 函数
向 dev 集合中插入单个文档。
{title:‘百战程序员’,description:‘身经百战,高薪相伴’,url:‘www.itbaizhan.cn’,tags:[‘javaWeb实战’,‘数据库实战’,‘微服务实战’]}
查看文档
成功插入
1.1.3 insertOne 函数
在 MongoDB3.2 以后的版本中,提供了 insertOne()函数用于插入文档。
向 dev 集合中插入单个文档。
{title:’ 尚 学 堂 大 数 据 ‘,description:’ 培 养 大 数 据 人 才 的 摇 篮’,url:‘www.bjsxt.com’,tags:[‘hadoop’,‘spark’,‘Hbase’]}
查看文档
1.2 插入多个文档
向集合中批量插入多个文档时,需要使用数组来存放文档。
语法格式:db.COLLECTION_NAME.insert([{},{},{}…])。
1.2.1 insert 或者 save 函数
向 dev 集合中批量插入多个文档
[{title:‘java’,tags:[‘JavaSE’,‘JavaEE’,‘JavaME’]},{title:‘ORM’,tags:[‘Mybatis’,‘Hibernate’]},{title:‘Spring’,tags:[‘SpringMVC’,‘SpringBoot’,‘SpringCloud’]}]
查看文档
成功插入
1.2.2 insertMany 函数
在 MongoDB3.2 以后的版本中,提供了 insertMany 函数用于插入文档。
语法格式:db.COLLECTION_NAME.insertMany([{},{},{},…])。
向 dev 集合中批量插入多个文档
[{title:‘Web’,tags:[‘JSP’,‘Servlet’]},{title:‘RPC’,tags:[‘RMI’,‘Dubbo’]},{title:‘DataBase’,tags:[‘Oracle’,‘MySQL’]}]
查看文档
成功插入
1.3 通过变量插入文档
Mongo Shell 工具允许我们定义变量。所有的变量类型为 var 类型。也可忽略变量类型。
变量中赋值符号后侧需要使用小括号来表示变量中的值。我们可以将变量作为任意插入文档的函数的参数。
语法格式:变量名=({变量值})
在mongoShell 中定义了一个变量 document
1.3.1 通过变量插入单个文档
定义变量
document=({title:‘SpringCloud’,tags:[‘Spring Cloud Netflix’,‘Spring Cloud Security’,‘Spring
Cloud Consul’]})
插入文档
查询文档
1.3.2 通过变量插入多个文档
我们也可以在变量中定义多个文档。
语法结构:变量名=([{},{},{},…])
插入文档
我们现在将多个文档放入到了一个变量中,所以在插入数据时,可直接使用插入单个文档的函数。
查询文档
变量的生命周期仅在当前的链接中生效,断开链接后失效
2 更新文档
MongoDB 通过 update 函数或者 save 函数来更新集合中的文档。
2.1 update 函数
update() 函数用于更新已存在的文档。,会去掉被更新字段之外的字段
语法格式:db.COLLECTION_NAME.update({查询条件},{更新内容},{更新参数(可选)})
将 SpringData 修改为 Spring Data
查看更新文档 只剩一个title 了
2.2 更新操作符
2.2.1 $set 操作符
$set 操作符:用来指定一个键并更新键值,若键不存在并创建。
语法格式:db.COLLECTION_NAME.update({查询条件},{更新操作符:{更新内容}})
将 SpringSecurity 修改为 Spring Security。
更新成功
修改后的结果
使用$set 在 title 为 SpringData 的文档中添加一个属性为 num 值为 1。
使用 字段进行更新如果字段有重复的,那么默认更新第一个字段
查看结果
批量更新
在更新文档时,可以使用 multi 参数实现批量更新。
添加测试数据
将 title 为 dev 的文档的 size 更新为 500
查看结果
第三个参数表示执行多个文档的更新
2.2.2 $inc 操作符
$inc 操作符:可以对文档的某个值为数字型(只能为满足要求的数字)的键进行增减的操作。
将 title 为 SpringData 的文档中的 num 值递增 1。
查看结果
以 10 的数量向上递增
以 -2 的方式向下递减
2.2.3 $unset 操作符
$unset 操作符:主要是用来删除键。
删除 title 为 SpringData 的文档中的 num 键。
1 仅仅是用来占位,给任何数字都行,并不是必须和 num 对应的值一样
查看结果
2.2.4 $push 操作符
$push 操作符:向文档的某个数组类型的键添加一个数组元素,不过滤重复的数据。添加时键存在,要求键值类型必须是数组;键不存在,则创建数组类型的键。
向 title 为 SpringData 的文档中添加一个数组键为 tags 值为[“Spirng Data Redis”]
查看结果 tags 之前不存在,调用函数之后创建了一个数组类型的键
2.2.5 $pop 操作符
$pop 操作符:删除数据元素。
1 表示从数组的尾部删除,从后往前删除,并不是说给一删除一条给二删除两条
删除 title 为 Spring 的文档中 tags 数组中的 Spring Cloud
查看结果
-1 表示从数组的头部删除元素
删除 title 为 Spring 的文档中 tags 数组中的 SpringMVC
查看结果
2.2.6 $pull 操作符
$pull 操作符:从数组中删除满足条件的元素
删除 title 为 Spring 的文档中 tags 数组中的 SpringBoot
查看结果
2.2.7 $pullAll 操作符
$pullAll 操作符:从数组中删除满足条件的多个元素
删除 title 为 java 的文档中 tags 数组中的 JavaSE、JavaEE
查看结果
2.2.8 $rename
$rename 操作符:对键进行重新命名。
将 title 为 Java 的文档中的 tags 键修改为 tag。
查看结果
2.3 使用 save() 函数更新文档
save() 方法通过传入的文档来替换已有文档。必须保证新的文档的ID和被替换文档的ID相同才能替换
语法格式:save({文档})
更新 title 为 SpringData 的文档,将 SpringData 修改为 Spring Data,并去掉 tags
查看结果
3 删除文档
3.1 remove() 函数
使用 remove()函数可删除集合中的指定文档。
语法格式:remove({指定删除条件},删除参数(可选参数))
删除 title 为 Spring Data 的文档,可使用该文档的 ObjectId 作为删除条件
如果使用的条件在集合中可以匹配多条数据,那么 remove()函数会删除所有满足条件的数据。我们可以在 remove 函数中给定 justOne,表示只删除第一条,在 remove 函数中给定参数 1 即可。
向 dev 集合中插入三条拥有相同 title 的测试数据
查看结果
只删除第一条数据
1 表示删除第一次插入的title 为 dev 的文档
查看结果
给 1 和 2 都一样都表示只删除一条
注意:remove() 方法 并不会真正释放空间。需要继续执行 db.repairDatabase() 来回收磁盘空间。
该命令的执行必须有dbAnyDataBase的权限
认证之后执行
3.2 deleteOne() 函数
deleteOne()函数是官方推荐删除文档的方法。会自动释放磁盘空间该方法只删除满足条件的第一条文档。
添加一条测试数据
查看结果
将test3 删除了
3.3 deleteMany() 函数
deleteMany 函数是官方推荐的删除方法。该方法删除满足条件的所有数据。
再次插入两条测试数据
查看结果
删除所有 title 为 dev 的文档
3.4 删除集合中的所有文档
向develop中插入测试数据
使用 remove 函数删除集合中的所有文档
语法格式:remove({})
使用 deleteMany 函数删除所有文档
语法格式:deleteMany({})
插入测试数据
删除
4 查询文档
4.1 find() 函数
在 MongoDB 中可以使用 find()函数查询文档。
语法格式为:find({查询条件(可选)},{指定投影的键(可选)})
如果未给定参数则表示查询所有数据。
pretty()函数可以使用格式化的方式来显示所有文档。
查询 dev 集合中的所有数据并格式化显示。
查询 title 为 DataBase 的文档并格式化显示。
4.2 findOne() 函数
findOne()函数只返回满足条件的第一条数据。如果未做投影操作该方法则自带格式化功能。
语法格式:findOne({查询条件(可选)},{投影操作(可选)})
如果一个参数都不给会查询所有数据,但是只显示只返回第一个文档
插入三条测试数据
使用 findOne 查询文档,条件为 title 的值为 dev 的文档。
只返回满足条件的第一条数据
4.3 模糊查询
在 MongoDB 中可以通过//与^ $实现模糊查询,注意使用模糊查询时查询条件不能放到双引号或单引号中。
查询文档中 title 的值含有 a 的内容。
使用^表示起始位置。
查询文档中 title 的值以 S 开头的内容。
使用$表示结尾位置。
查询文档中 title 的值以结尾的内容。
4.4 投影操作
4.4.1 find() 函数投影操作
在 find 函数中我们可以指定投影键。
语法格式为:find({查询条件},{投影键名:1(显示该列)|0(不显示该列),投影键名:1|0,…})
id 列默认为显示列。如果不显示id 可在投影中通过 0 过滤。
通过给 参数 0 设置不显示 _id 列
4.4.2 findOne 函数投影操作
在 findOne 函数中我们可以指定投影列。
语法格式为:findOne({查询条件},{投影键名:1(显示该列)|0(不显示该列)})
5 条件操作符
条件操作符用于比较两个表达式并从 mongoDB 集合中获取数据。
语法格式:find({键:{操作符:条件}})或者 findOne({键:{操作符:条件}})
5.1 $gt
(>) 大于操作符
我们可以使用$gt 操作做大于的条件判断。该操作符可以数字或日期进行判断。
添加测试数据。
查询 size 大于 300 的文档。
5.2 $lt
(<) 小于操作符
我们可以使用$lt 操作做小于的条件判断。该操作符可以数字或日期进行判断。
查询 size 小于 300 的文档。
5.3 $gte
(>=)大于或等于操作符
我们可以使用$gte 操作做大于或等于的条件判断。该操作符可以数字或日期进行判断。
查询 size 大于或等于 300 的文档。
5.4 $lte
(<=)小于或等于操作符
我们可以使用$lte 操作做小于或等于的条件判断。该操作符可以数字或日期进行判断。
查询 size 小于或等于 300 的文档。
5.5 $eq
(==)等于操作符
我们可以使用$eq 操作做相等的条件判断。
查询 size 等于 300 的文档。
5.6 $ne
(!=)不等操作符
我们可以使用$ne 操作做不等的条件判断。
查询 size 不等于 300 的文档。
没有size 列的也符合条件
5.7 $and
我们可以使用KaTeX parse error: Expected '}', got 'EOF' at end of input: … **语法格式为:find({
and:[{条件一},{,条件二},…]})
插入测试数据
如果在查询中给定了多个查询条件,条件之间的关系默认为 and 关系。
查询 size 大于 100 并且小于 300 的文档。
使用$and 指定多条件关系。
查询 size 大于 100 并且小于 300 的文档。
5.8 $or
我们可以使用KaTeX parse error: Expected '}', got 'EOF' at end of input: …系。 语法格式为:find({
or:[{条件一},{条件二},…]})
查询 title 的值为 test2 或者 size 大于 400 的文档。
5.9 a n d 与 and 与 and与or 联合使用
查询 title 为 test5 并且 size 等于 500,或者 size 小于 400 的文档。
5.10 $type 操作符
$type 操作符是基于 BSON 类型来检索集合中匹配的数据类型,并返回结果。
插入测试数据
查询 title 的值为 number 类型。
typeof 函数判断类型
6 Limit 函数与 与 Skip 函数
6.1 Limit 函数
如果需要在 MongoDB 中读取指定数量的数据记录,可以使用 MongoDB 的 Limit 函数,limit()函数接受一个数字参数,该参数指定从 MongoDB 中读取的记录条数。
语法格式:db.COLLECTION_NAME.find().limit(NUMBER)
返回的是前两条
前两条数据
6.2 Skip 函数
我们除了可以使用 limit()函数来读取指定数量的数据外,还可以使用 skip()函数来跳过指定数量的数据,skip 函数同样接受一个数字参数作为跳过的记录条数。
语法格式:db.COLLECTION_NAME.find().limit(NUMBER).skip(NUMBER)
skip函数和limit函数的位置谁前谁后都一样
取前5条数据
跳过第一条数据,往后取5条数据
我们可以使用 skip 函数与 limit 函数实现 MongoDB 的分页查询,但是官方并不推荐这样做,因为会扫描全部文档然后在返回结果,效率过低。
7 MongoDB 排序
在 MongoDB 中使用 sort() 函数对查询到的文档进行排序,sort() 函数可以通过参数指定排序的字段,并使用 1 和 -1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
语法格式:db.COLLECTION_NAME.find().sort({排序键:1})
现在按照插入文档的顺序排序
7.1 升序排序
查询 size 的值为 number 类型的文档,显示 title,size 的内容,并对 size 做升序排序。
7.2 降序排序
查询 size 的值为 number 类型的文档,显示 title,size 的内容,并对 size 做降序排序。
7.3 对字符串排序
对字符串排序的方式采用的是大小写分离排序。
1:升序
-1:降序
8 MongoDB 索引
索引通常能够极大的提高查询的效率,如果没有索引,MongoDB 在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对系统的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构
8.1 创建索引
在 MongoDB 中会自动为文档中的_Id(文档的主键)键创建索引,与关系型数据的主键索引类似。
我们可以使用 createIndex()函数来为其他的键创建索引。在创建索引时需要指定排序规则。
1 按照升序规则创建索引,-1 按照降序规则创建索引。
在创建索引时,需要使用具有 dbAdmin 或者 dbAdminAnyDatabase 角色的用户。
语法格式:db.COLLECTION_NAME.createIndex({创建索引的键:排序规则,…},{创建索引的参数(可选参数)})
参数说明
为 dev 集合中的 title 键创建索引,并让创建工作在后台运行。
注意权限和用户
8.2 查看索引
8.2.1 查看集合索引
我们可以通过 getIndexes()或者 getIndexSpecs()函数查看集合中的所有索引信息。
语法格式:db.COLLECTION_NAME.getIndexes()
语法格式:db.COLLECTION_NAME.getIndexSpecs()
使用 getIndexes()函数查看当前 dev 集合中的索引
MongoDB会自动为主键创建索引信息 ns:当前索引所在的位置 v:索引的版本号
title_1 : 是默认名字,键名+_+排序规则
使用 getIndexSpecs()函数查看当前 dev 集合中的索引
8.2.2 查看索引键
我们可以通过使用 getIndexKeys()函数查看集合的索引键。
语法格式:db.COLLECTION_NAME.getIndexKeys();
查看 dev 集合中的索引键
8.2.3 查看索引 大小
我们可以通过 totalIndexSize()函数来查看当前集合中索引的大小,单位为字节。
语法格式:db.COLLECTION_NAME.totalIndexSize(detail)
参数解释:
detail 可选参数,传入除 0 或 false 外的任意数据,那么会显示该集合中每个索引的大小及集合中索引的总大小。
如果传入 0 或 false 则只显示该集合中所有索引的总大小。默认值为 false。
查看 dev 集合中所有索引的总大小。
查看 dev 集合中的每个索引的大小以及总大小
中括号里面给 1 或者 true
8.3 修改索引
MongoDB 没有单独的修改索引函数,如果要修改某个索引,需要先删除旧的索引,再创建新的索引。
8.4 删除索引
8.4.1 删除集合中的指定索引
我们可以通过 dropIndex()函数来删除指定索引。
语法格式:db.COLLECTION_NAME.dropIndex(“索引名称”)。
删除 title 键的索引
8.4.2 删除集合中的全部索引
我们可以使用 dropIndexes()函数删除集合中的全部索引,_id 键的索引除外(默认索引不删除)。
语法格式:db.COLLECTION_NAME.dropIndexes()
8.5 重建索引
我可以使用 reIndex()函数重建索引。重建索引可以减少索引存储空间,减少索引碎片,优化索引查询效率。**一般在数据大量变化后,会使用重建索引来提升索引性能。**重建索引是删除原索引重新创建的过程,不建议反复使用。
语法格式:db.COLLECTION_NAME.reIndex()
此函数会将当前集合所有索引都做重建处理
8.6 MongoDB 中的索引类型
在 MongoDB 中支持多种类型的索引,包括单字段索引、复合索引、多 key 索引、文本索引等,每种类型的索引有不同的使用场合。
8.6.1 单字段索引(Single Field Index )
所谓单字段索引是指在索引中只包含了一个键。查询时,可加速对该字段的各种查询请求,是最常见的索引形式。MongoDB 默认创建的_Id 索引也是这种类型。我们可以使用createIndexes({索引键:排序规则})函数来创建单字段索引。
语法格式:db.COLLECTION_NAME.createIndexes({索引键名:排序规则})
为 dev 集合中的 title 键创建单字段索引
8.6.2 交叉索引
所谓交叉索引就是为一个集合的多个字段分别建立索引,在查询的时候通过多个字段作为查询条件,这种情况称为交叉索引。
在查询文档时,在查询条件中包含一个交叉索引键或者在一次查询中使用多个交叉索引键作为查询条件都会触发交叉索引。
为 dev 集合中的 size 键创建交叉索引。
这两个索引就是一个交叉索引
8.6.3 复合索引(Compound Index )
复合索引是 Single Field Index 的升级版本,它针对多个字段联合创建索引,先按第一个字段排序,第一个字段相同的文档按第二个字段排序,依次类推。
语法格式:db.COLLECTION_NAME.createIndex({索引键名:排序规则, 索引键名:排序规则,…});
复合索引能满足的查询场景比单字段索引更丰富,不光能满足多个字段组合起来的查询,也能满足所以能匹配符合索引前缀的查询。
复合索引具有最左前缀的原则,如果字段A和字段B创建复合索引,查询条件为A时会触发复合索引,但是查询条件为B时不会触发复合索引
删除 dev 中的交叉索引。
创建 title 与 size 的符合索引
查看索引
8.6.4 多 key 索引 (Multikey Index )
当索引的字段为数组时,创建出的索引称为多 key 索引,多 key 索引会为数组的每个元素建立一条索引。只对数组类型的键生效
语法格式:db.COLLECTION_NAME.createIndex({数组键名:排序规则});
为 dev 集合中 tags 键创建多 Key 索引
查看索引
8.7 索引额外属性
MongoDB 除了支持多种不同类型的索引,还能对索引定制一些特殊的属性。
8.7.1 唯一索引 (unique index)
唯一索引会保证索引对应的键不会出现相同的值,比如_id 索引就是唯一索引
语法格式:db.COLLECTION_NAME.createIndex({索引键名:排序规则},{unique:true})
如果唯一索引所在字段有重复数据写入时,抛出异常。
键名重复
删除 dev 集合中的索引。为 dev 集合中的 title 键建立唯一索引
创建出错,dev 键有多个
删除掉重复的键
title键已经没有重复的了
创建成功
插入 title 相同的值测试唯一索引
已经存在无法插入
8.7.2 部分索引 (partial index):
部分索引是只针对符合某个特定条件的文档建立索引,3.2 版本才支持该特性。
MongoDB 部分索引只为那些在一个集合中,满足指定的筛选条件的文档创建索引。由于部分索引是一个集合文档的一个子集,因此部分索引具有较低的存储需求,并降低了索引创建和维护的性能成本。部分索引通过指定过滤条件来创建,可以为 MongoDB 支持的所有索引类型使用部分索引。
简单点说:部分索引就是带有过滤条件的索引,即索引只存在与某些文档之上
语 法 格 式 : db.COLLECTION_NAME.createIndex({ 索 引 键 名 : 排 序 规则},{partialFilterExpression:{键名:{匹配条件:条件值}}})
为 dev 集合中的 size 键创建部分索引。条件为大于 300
查询时size的值满足了size的查询条件时会触发索引
查看索引
注意:部分索引只为集合中那些满足指定的筛选条件的文档创建索引。如果你指定的partialFilterExpression 和唯一约束、那么唯一性约束只适用于满足筛选条件的文档。具有唯一约束的部分索引不会阻止不符合唯一约束且不符合过滤条件的文档的插入。
eg:size小于300的索引可以重复,但是size大于300满足部分索引的创建条件时,不予许重复
8.7.3 稀疏索引(sparse index)
稀疏索引仅包含具有索引字段的文档的条目,即使索引字段包含空值也是如此。索引会跳过缺少索引字段的任何文档。索引是“稀疏的”,因为它不包含集合的所有文档。相反,非稀疏索引包含集合中的所有文档,为那些不包含索引字段的文档存储空值。
语法格式:db.COLLECTION_NAME.createIndex({索引键名:排序规则},{sparse:true})
为 dev 集合中的 tag 键创建稀疏索引
查看索引
注意:从 MongoDB 3.2 开始,MongoDB 提供了创建部分索引的选项 。部分索引提供了稀疏索引功能的超集。如果您使用的是 MongoDB 3.2 或更高版本,则部分索引应优先于稀疏索引。
8.8 覆盖索引查询
官方的 MongoDB 的文档中说明,覆盖查询是以下的查询:
- 所有的查询字段是索引的一部分
2. 所有的查询返回字段在同一个索引中
由于所有出现在查询中的字段是索引的一部分, MongoDB 无需在整个数据文档中检索匹配查询条件和返回使用相同索引的查询结果。(查询的条件和查询返回的字段全部来自索引)
因为索引存在于 RAM 中,从索引中获取数据比通过扫描文档读取数据要快得多。
如有如下索引:
db.stu.createIndex({title:1,:size:1})
那么执行如下查询时,该索引会覆盖查询:
db.stu.find({title:“dev”},{size:1,id:0}) 查询条件来自于索引,返回的结果也来自于索引
也就是说,对于上述查询,MongoDB 的不会去数据库文件中查找。相反,它会从索引中提取数据,这是非常快速的数据查询。
由于我们的索引中不包括 _id 字段,id 在查询中会默认返回,我们可以在 MongoDB的查询结果集中排除它。
8.9 查询计划
在 MongoDB 中通过 explain()函数启动执行计划,我们可以使用查询计划分析索引的使用情况,可通过查看详细的查询计划来决定如何优化。
语法结构:db.COLLECTION_NAME.find().explain()
删除 dev 集合中的所有索引。通过查询计划查看查询 size 键的值大于 200 的查询结果为 size 键创建单字段索引。再次查看查询结果。
不通过索引看查询计划
全表扫描
创建索引
查看执行结果
索引扫描
8.10 使用索引注意事项
既然索引可以加快查询速度,那么是不是只要是查询语句,就创建索引呢?答案是否定的。因为索引虽然加快了查询速度,但索引也是有代价的:索引文件本身要消耗存储空间,同时索引会加重插入、删除和修改记录时的负担,另外,数据库在运行时也要消耗资源维护索引,因此索引并不是越多越好。
那么什么情况不建议创建索引呢?例如一两千条甚至只有几百条记录的表,没必要建索引,让查询做全集合扫描就好了。至于多少条记录才算多?我个人建议以 2000 作为分界线,记录数不超过 2000 可以考虑不建索引,超过 2000 条可以酌情考虑创建索引。
8.10.1 如何创建合适的索引
8.10.1.1 建立合适的索引
为每一个常用查询结构建立合适的索引。
复合索引是创建的索引由多个字段组成,例如:
db.test.createIndex({“username”:1, “age”:-1})
交叉索引是每个字段单独建立索引,但是在查询的时候组合查找,例如:
db.test.createIndex({“username”:1})
db.test.createIndex({“age”:-1})
db.test.find({“username”:“kaka”, “age”: 30})
交叉索引的查询效率较低,在使用时,当查询使用到多个字段的时候,尽量使用复合索引,而不是交叉索引。
8.10.1.2 复合索引的字段排列顺序
当我们的组合索引内容包含匹配条件以及范围条件的时候,比如包含用户名(匹配条件)以及年龄(范围条件),那么匹配条件应该放在范围条件(大于,小于)之前。
比如需要查询:
db.test.find({“username”:“kaka”, “age”: {$gt: 30}})
那么复合索引应该这样创建:
db.test.ensureIndex({“username”:1, “age”:-1})
8.10.1.3 查询时尽可能仅查询出索引字段
有时候仅需要查询少部分的字段内容,而且这部分内容刚好都建立了索引,那么尽可能只查询出这些索引内容,需要用到的字段显式声明(_id 字段需要显式忽略!)。因为这些数据需要把原始数据文档从磁盘读入内存,造成一定的损耗。
比如说我们的表有三个字段:
name, age, mobile
索引是这样建立的:
db.stu.createIndex({“name”:1,“age”:-1})
我们仅需要查到某个用户的年龄(age),那可以这样写:
db.stu.find({“name”:“kaka”}, {"_id":0, “age”:1})
注意到上面的语句,我们除了”age”:1 外,还加了”_id”:0,因为默认情况下,_id
都是会被一并查询出来的,当不需要_id 的时候记得直接忽略,避免不必要的磁盘操作。
8.10.1.4 对现有的数据大表建立索引的时候,采用后台运行方式
在对数据集合建立索引的过程中,数据库会停止该集合的所有读写操作,因此如果建立索引的数据量大,建立过程慢的情况下,建议采用后台运行的方式,避免影响正常业务流程。
db.stu.ensureIndex({“name”:1,“age”:-1},{“background”:true})
8.11 索引限制
8.11.1 额外开销
每个索引占据一定的存储空间,在进行插入,更新和删除操作时也需要对索引进行操作。
所以,如果你很少对集合进行读取操作,建议不使用索引。
8.11.2 内存使用
由于索引是存储在内存(RAM)中,你应该确保该索引的大小不超过内存的限制。
如果索引的大小大于内存的限制,MongoDB 会删除一些索引,这将导致性能下降。
8.11.3 查询限制
索引不能被以下的查询使用:
正则表达式(最左匹配除外)及非操作符,如 $nin, $not, 等。
算术运算符,如 $mod, 等。
所以,检测你的语句是否使用索引是一个好的习惯,可以用 explain 来查看。
8.11.4 最大范围
集合中索引不能超过 64 个
索引名的长度不能超过 128 个字符
一个复合索引最多可以有 31 个字段
8.12 正则查询
MongoDB 中查询条件也可以使用正则表达式作为匹配约束。
语法格式:db.COLLECTION_NAME.find({字段名:正则表达式});
或
db.COLLECTION_NAME.find({字段名:{
r e g e x : 正 则 表 达 式 , regex:正则表达式, regex:正则表达式,options:正则选项}});
正则表达式格式:/xxx/
正则选项:
i - 不区分大小写以匹配大小写的情况。
m - 多行查找,如果内容里面不存在换行符号(例如 \n)或者条件上没有(start/end),该选项没有任何效果
x - 设置 x 选项后,正则表达式中的非转义的空白字符将被忽略。需要 r e g e x 与 regex 与 regex与options语法
s - 允许点字符(即.)匹配包括换行符在内的所有字符。需要 r e g e x 与 regex 与 regex与options 语法
i,m,x,s 可以组合使用。
查询 dev 集合中 title 字段以’S’开头的数据
db.dev.find({title:/^S/})
db.dev.find({title:{$regex:/^S/}})
查询 dev 集合中 title 字段以’g’结尾的数据
db.stu.find({title:/g$/})
db.stu.find({title:{ r e g e x : / g regex:/g regex:/g/}});
查询 dev 集合中 dev 字段中包含’ing’的数据
db.stu.find({title:/ing/});
db.stu.find({title:{$regex:/ing/}});
查询 dev 集合中 title 字段以’S’开头的数据,且忽略大小写
db.dev.find({title:/^S/i}); 给 S 或者 s 都行因为忽略大小写
db.dev.find({title:{$regex:/^S/i}});
db.dev.find({title:{$regex:/^S/, $options:“i”}});
查询 dev 集合中 title 字段已’S’开头、'g’结尾的数据
*db.dev.find({title:/^S.g$/}); * :零次或多次
db.dev.find({title:{ r e g e x : / S . ∗ g regex:/^S.*g regex:/S.∗g/}});
查询 dev 集合中 title 字段以’S’或’t’开头的数据
db.dev.find({title:{$in:[/^S/, /^t/]}});
查询 dev 集合中 title 字段不以’S’开头的数据
db.dev.find({title:{$not:/^S/}});
查询 dev 集合中 title 字段不以’S’或’t’开头的数据
db.stu.find({title:{$nin:[/^S/, /^t/]}});
9 MongoDB 聚合查询
在 MongoDB 中我们可以通过 aggregate()函数来完成一些聚合查询,aggregate()函数主要用于处理诸如统计,平均值,求和等,并返回计算后的数据结果。
语法格式:
db.COLLECTION_NAME.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"分组键名",“KaTeX parse error: Expected '}', got 'EOF' at end of input: …....,别名:{聚合运算:"运算列”}}},{条件筛选:{键名:{运算条件:运算值}}}])
常见的 mongo 的聚合操作和 mysql 的查询做类比
$match 如果在 $group 前会当做where处理,如果在后侧当 having处理
9.1 求和 - $sum
查询 dev 集合中一共有多少个文档。
相当于 sql 语句:SELECT count(*) AS count FROM dev
db.dev.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: …id:null,count:{
sum:1}}}])
g r o u p : 分 组 , 代 表 聚 合 的 分 组 条 件 i d : 分 组 的 字 段 。 相 当 于 S Q L 分 组 语 法 g r o u p b y c o l u m n n a m e 中 的 c o l u m n n a m e 部 分 。 如 果 根 据 某 字 段 的 值 分 组 , 则 定 义 为 i d : ′ group:分组,代表聚合的分组条件 _id:分组的字段。相当于 SQL 分组语法 group by column_name 中的 column_name 部分。 如果根据某字段的值分组,则定义为_id:' group:分组,代表聚合的分组条件id:分组的字段。相当于SQL分组语法groupbycolumnname中的columnname部分。如果根据某字段的值分组,则定义为id:′字段名’。所以此案例中的 null 代表一个固定的字面值’null’。
count:返回结果字段名。可以自定义,类似 SQL 中的字段别名。
$sum:求和表达式。相当于 SQL 中的 sum()。
1:累加值。
查询 dev 集合中的所有 size 键中的值的总和。
相当于 sql 语句:SELECT sum(size) AS totalSize FROM dev
db.dev.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: …ull,totalSize:{
sum:"$size"}}}])_
“$size”:代表文档中的 szie 字段的值。
对每一个 title 进行分组并计算每组中的 size 的总和
相当于 sql 语句:SELECT title AS _id , sum(size) AS totalSize FROM dev GROUP BY title
db.dev.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"title",totalSize:{
s u m : " sum:" sum:"size"}}}])
9.2 条件筛选 - $match
查询 dev 集合有多少文档的 size 大于 200。
db.dev.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: match:{size:{
gt:200}}},{
KaTeX parse error: Expected '}', got 'EOF' at end of input: …ull,totalSize:{
sum:1}}}])
相当于 SQL 语句:SELECT count(*) FROM dev WHERE size > 200
$match:匹配条件,相当于 SQL 中的 where 子句,代表聚合之前进行条件筛选。
_查询 dev 集合,根据 title 分组计算出每组的 size 的总和,并过滤掉总和小于等于 200的文档。
db.dev.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: group:{_id:"title",totalSize:{
s u m : " sum:" sum:"size"}}},{
KaTeX parse error: Expected '}', got 'EOF' at end of input: …ch:{totalSize:{
gt:200}}}])
相当于 SQL 语句:SELECT sum(size) AS totalSize FROM dev GROUP BY title HAVING totalSize > 200
9.3 最大值 - $max
查询 dev 集合中 size 最大的文档。
db.dev.aggregate([{
KaTeX parse error: Expected '}', got 'EOF' at end of input: …:null,maxSize:{
max:"$size"}}}])
m a x : " max:" ma