1MongoDB简介

MongoDB 是一种NoSQL 数据库,存储的数据对象由键值对组成。MongoDB 所有存储在集合中的数据都是 BSON 格式。BSON 是一种类似 JSON 的二进制形式的存储格式,是 Binary JSON 的简称。如下所示:

无懈可击的MongoDB使用教程_java

下面对照关系型数据库介绍一些 MongoDB 里面的基本概念:

关系数据库术语MongoDB术语说明
databasedatabase数据库
tablecollection数据库表/集合
rowdocument记录行/文档
columnfield数据字段/域
indexindex索引
primary keyprimary key主键,Mongodb自动将_id字段设置为主键

通过以下对比可以更理解 MongoDB :

id姓名年龄性别
1张三23
2李四21

上述关系型数据在 MongoDB 中的数据形式为:

无懈可击的MongoDB使用教程_java_02

广告时间

前手机淘宝前端负责人winter老师确认参加腾讯TLC大会,他将面对面跟你聊聊技术管理成长中的对与错目前七折票火热销售中,扫描上方二维码查看具体详情!

2MongoDB 基本操作

本节主要介绍通过命令行操作 MongoDB,以 MongoDB 安装在 CentOS 上为例进行说明。

2.1 db、集合等基本操作

DB 的查看、创建、删除,集合的查看、创建、删除等操作方式如下:

无懈可击的MongoDB使用教程_java_03

2.2 数据插入

插入数据有4种方法:insert、insertOne、insertMany、save,下面通过例子详细介绍。

无懈可击的MongoDB使用教程_java_04

2.3 数据修改

修改数据有2种方法:update、save,下面详细介绍。

2.3.1 update

首先,看一下 update 的语法格式,请格外注意一些可选参数的值,这将直接影响你的修改结果:

无懈可击的MongoDB使用教程_java_05

假设有这样一张学生成绩表:

无懈可击的MongoDB使用教程_java_06

xiaoming同学发现老师把她的c++课程分数录错了,需要修改为75分:

无懈可击的MongoDB使用教程_java_07

老师发现把 xiaoming 同学的名字录错了,需要全部修改过来:

无懈可击的MongoDB使用教程_java_08

将 xming 的 java 课程分数改为95分,如果找不到,就插入一条记录

无懈可击的MongoDB使用教程_java_09

2.3.2 save

save 方法通过传入的文档来替换已有文档。语法格式如下:

无懈可击的MongoDB使用教程_java_10

还以上面那张学生成绩表为例:

无懈可击的MongoDB使用教程_java_11

2.4 数据删除

数据删除可以使用 deleteOne、deleteMany、remove,下面详细介绍。

2.4.1 deleteOne 和 deleteMany

使用方法如下:

无懈可击的MongoDB使用教程_java_12

2.4.2 remove

首先还是来看语法格式:

无懈可击的MongoDB使用教程_java_13

删除 xming 的所有成绩记录:

ps:remove 现在已经过时了现在官方推荐使用 deleteOne 和 deleteMany 方法。

2.5 数据查询

数据查询的方法有 findOne 和 find,二者参数等用法一样,但是 findOne 只返回一条匹配的数据,find 返回全部的匹配数据,下面主要介绍 find 的用法。

2.5.1 条件操作符

操作sql查询写法mongo查询写法
等于select * from my_col where score = 75;db.my_col.find({"score": 75}).pretty()
小于select * from my_col where score < 75;db.my_col.find({"score": {$lt: 75}}).pretty()
小于等于select * from my_col where score <= 75;db.my_col.find({"score": {$lte: 75}}).pretty()
大于select * from my_col where score > 75;db.my_col.find({"score": {$gt: 75}}).pretty()
大于等于select * from my_col where score >= 75;db.my_col.find({"score": {$gte: 75}}).pretty()
不等于select * from my_col where score != 75;db.my_col.find({"score": {$ne: 75}}).pretty()

ps:pretty 能让查询结果以格式化的 json 形式打印出来,便于查看

2.5.2 排序、limit 与 skip

以分数从高到低显示学生的 c++ 课程成绩,只显示第10名到第20名的学生:

无懈可击的MongoDB使用教程_java_14

2.5.3 复合条件查询 and、or

and:find 方法可以传入多个键值对,每个键值对以逗号隔开,即常规 SQL 的 AND 条件

查询 xiaoming 同学的 c++ 课程成绩:

无懈可击的MongoDB使用教程_java_15

查询分数在75到85分之间的成绩记录:

无懈可击的MongoDB使用教程_java_16

or:MongoDB OR 条件语句使用了关键字 $or,语法格式如下:

无懈可击的MongoDB使用教程_java_17

查询 xiaoming 或 zhangsan 的课程成绩:

无懈可击的MongoDB使用教程_java_18

and + or 复合查询:

查询 xiaoming 的 c++ 或者 python 课程的成绩:

无懈可击的MongoDB使用教程_java_19

2.5.4 包含in、不包含nin、全部all

查询 xiaoming、zhangsan 和 lisa 的成绩:

无懈可击的MongoDB使用教程_java_20

查询除了 xiaoming、zhangsan 和 lisa 之外,其他人的成绩:

无懈可击的MongoDB使用教程_java_21

in和nin比较好理解,跟sql的用法类似,all类似于in,不同的地方是,in只需要满足列表中的一个值即可,而all需要满足列表中的全部值。比如,有下面这样一张课程表,表示每个学生修的课程:

无懈可击的MongoDB使用教程_java_22

需要找出修了 c++ 和 java课程的学生:

无懈可击的MongoDB使用教程_java_23

2.5.5 判断字段是否存在 exists

比如,有下面一张表,表示学生信息:无懈可击的MongoDB使用教程_java_24

需要找出没有 tel 字段的学生:

2.5.6 空值处理 null

以上面的学生信息表为例,找出 tel 为空值的学生:

这时候把 tel 字段不存在和 tel 值为 null 的情况都查出来了!如果只想找 tel 值为 null 的情况:

2.5.7 取模运算 mod

比如,查找学生成绩取模10 等于0 的数据(即100、90、80...等等):

2.5.8 正则匹配 regex

查询学生名字以a开头的学生成绩:

无懈可击的MongoDB使用教程_java_25

2.5.9 获取查询结果条数 count

获取学生成绩记录的条数:

无懈可击的MongoDB使用教程_java_26

当使用 limit 方法限制返回的记录数时,默认情况下 count 方法仍然返回全部记录条数。如果希望返回限制之后的记录数量,要使用 count(true) 或者 count(非0):

无懈可击的MongoDB使用教程_java_27

2.5.10 distinct

查询课程成绩表中所有学生的名单:

无懈可击的MongoDB使用教程_java_28

2.6 聚合aggregate

在MongoDB中,使用聚合框架可以对集合中的文档进行变换和组合,完成一些复杂的查询操作。聚合框架通过多个构件来创建一个管道(pipeline),用于对一连串的文档进行处理。这些构件包括但不限于:

操作符意义
$match筛选
$project投射,选择想要的字段或对字段进行重命名
$group分组
$unwind拆分
$sort排序
$limit限制查询条数
$skip跳过一些条数

当需要使用多个操作符来完成文档的聚合时,我们可以传入一个数组条件,这也是aggregate的常见用法:

无懈可击的MongoDB使用教程_java_29

$match用于对文档集合进行筛选,之后就可以在筛选得到的文档子集上做聚合。"$match"可以使用所有常规的查询操作符("$gt"、"$lt"、"$in"等)。通常,在实际使用中应该尽可能将"$match"放在管道的前面位置。这样做有两个好处:一是可以快速将不需要的文档过滤掉,以减少管道的工作量;二是如果在投射和分组之前执行"$match",查询可以使用索引。

$project可以从子文档中提取字段,可以重命名字段。例如,查找学生课程成绩,不显示 _id 字段,显示姓名、课程、成绩字段,同时将 name 字段重命名为 student_name:

无懈可击的MongoDB使用教程_java_30

$sort、$skip、$limit 的用法比较好理解,就不多做说明。

$group 类似于 sql 中的 group by,主要用于数据处理,比如,计算每个学生的总课程成绩:

无懈可击的MongoDB使用教程_java_31

$sum 可以 替换成操作符 $avg、$min、$max,分别表示求平均成绩、最低成绩、最高成绩。

$unwind 可以将数组中的每一个值拆分为单独的文档,比如有下面一条记录,记录了一篇博客以及下面的评论:

现在要找到 lisa 的评论,可以先使用 $unwind 将每条评论拆分为一个独立的文档,然后再进行 match 查询:

2.7 索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。这种扫描全集合的查询效率是非常低的,特别在处理大量的数据时,查询可以要花费几十秒甚至几分钟,这对网站的性能是非常致命的。索引是特殊的数据结构,索引存储在一个易于遍历读取的数据集合中,索引是对数据库表中一列或多列的值进行排序的一种结构。

创建索引的基本语法如下:

无懈可击的MongoDB使用教程_java_32

对学生成绩表创建索引:

无懈可击的MongoDB使用教程_java_333可视化工具

MongoDB有一款跨平台的可视化工具Robo 3T,非常简洁易用。

下载安装地址:https://robomongo.org/download

下载安装成功之后,点击 file → connect,弹出以下小窗口,然后点击create,新建配置:

无懈可击的MongoDB使用教程_java_34

填入正确的地址和端口,保存即可。

无懈可击的MongoDB使用教程_java_35

按照上述教程安装之后,如果你连不上所配置的MongoDB,排除网络原因,可能是因为DB服务配置的监听地址是127.0.0.1,需要改成0.0.0.0哦。

双击配置好的连接,即可进入交互界面,如下图所示,左边是数据库和集合等信息,右边是查询结果。可以在命令行输入查询命令然后点击执行,进行过滤等操作。

无懈可击的MongoDB使用教程_java_36

还可以直接右键对文档进行查看、编辑等操作,非常方便。

无懈可击的MongoDB使用教程_java_37