注意:本文的操作都是在 macOS 上完成的,对于一些平台相关的操作在其它平台怎么完成,相关小节会有说明。一般来说,因为 macOS 是 Unix 系统,所以在 Unix/Linux 系的其它平台(比如 Ubuntu、CentOS 等)上的操作与 macOS 基本一致,只有 Windows 在某些操作上有些不同。
1 MongoDB 安装
前面我们使用 MongoDB 大学提供的服务器地址、用户名和密码能够登录到 MongoDB 服务器,但在那上面我们只有读的权限。为方便后面实验,我们需要搭建可以自主管理的 MongoDB 服务,在上面我们不仅能读,还能写以及进行其他一些管理操作。
这里有 2 种选择,一是 MongoDB Atlas,二是在本地安装 MongoDB。
1.1 使用云服务安装
MongoDB Atlas 是 MongoDB 官方的一个云服务,你只要在网页上面简单填写一些信息,提交后后台会自动给你创建相应的 MongoDB 实例,并且上面有免费的规格可选。对于初学 MongoDB 的同学来说,这应该是最合适的,但是由于这是国外的服务,在本地使用客户端连接时,响应太慢,在国内不大推荐这种方式。我之前试用了下,选择的 AWS 新加坡的机房,一个操作平均要等 1s 才返回,这影响学习的效率。如果你比较好奇,还是可以去体验下,具体怎么申请、使用,可以查看官方的 Atlas 文档(参考链接 1)。
1.2 本地安装
下面说下本地安装的步骤
(1)下载 MongoDB
MongoDB 分为社区版和商业版,前者免费,后者收费。商业版提供额外的管理工具、可视化工具等。我们选择社区版即可。
下载地址:
https://www.mongodb.com/try/download/community
下载时需要先提供一些信息
- Version,MongoDB 版本,选择比较新的稳定版就行(刚开始写文章的时候还只有 4.2.x,写的太慢,写完了 4.4.0 已经出来了,你可以直接选择最新的,安装过程都差不多)
- Platform,操作系统,根据你的情况选择就行
- Package,下载的文件类型,这里我推荐都选择压缩包(macOS 和 Linux 平台是 tgz,Windows 是 zip),下载解压后是可以直接运行的
以 macOS 为例,选择的选项如下
然后点击下载即可
(2)安装
下载后的压缩包解压后,bin 目录下文件是可以直接运行的,只是每次运行都需要在终端中敲入全路径,比较麻烦。这里的安装其实就是将该 bin 目录添加到环境变量 PATH,方便我们运行对应的可执行程序。
以 macOS 为例,假设我们下载的压缩包在 ~/Download
目录下,文件名为 mongodb-macos-x86_64-4.2.8.tgz
,先切换至对应目录将其解压
$ cd ~/Download
$ tar -zxvf mongodb-macos-x86_64-4.2.8.tgz
然后将解压后的文件夹 mongodb-macos-x86_64-4.2.8
移至某个目录,比如 /opt
(看你的习惯来)
$ sudo mv mongodb-macos-x86_64-4.2.8 /opt/mongodb-macos-x86_64-4.2.8
最后我们将路径 /opt/mongodb-macos-x86_64-4.2.8/bin
添加到环境变量 PATH,打开文件 ~/.bashrc
,在最后一行添加
export PATH="/opt/mongodb-macos-x86_64-4.2.8/bin:$PATH"
加载文件,以使修改生效
$ source ~/.bashrc
你也可以关闭终端后重新打开以使新配置生效。这里的配置仅是针对当前用户的,如果需要计算机上的所有用户有效,可以修改文件 /etc/bashrc
。
试下看有没有配置成功
$ mongod --version
如果出现类似的输出表示配置一切正常
db version v4.2.8
git version: 43d25964249164d76d5e04dd6cf38f6111e21f5f
allocator: system
modules: none
build environment:
distarch: x86_64
target_arch: x86_64
上面的安装过程适用于 Unix/Linux 系统。如果是 Windows,整个安装思路是一致的,就是配置环境变量的方法有些差异,在搜索引擎上搜索「win 环境变量 path 配置」就能找到解决办法,这里不赘述。另外,上面文件路径中出现的 ~
指的是 Unix/Linux 中的用户目录,Windows 的话你可以对应到 C 盘的 Users 目录下与你用户名相同的子目录。
(3)启动 mongod
创建目录用于存放数据库的数据文件、日志文件,目录名以及位置你可以自己定
$ mkdir ~/mongodb42
这里在用户目录下创建了 mongodb42 文件夹,切换至该文件夹并新建数据目录 data
$ cd ~/mongodb42
$ mkdir data
启动 mongod
$ mongod --dbpath data --logpath mongod.log --bind_ip=127.0.0.1 --port=27017 --fork
了解下启动参数
--dbpath
指定数据文件存放目录--logpath
指定日志文件位置--bind_ip
指定要绑定的 IP,默认是 localhost--port
指定监听端口,默认是 27017--fork
设置 mongod 在后台运行,如果不带这个选项的话,mongod 会在前台运行
当你看到类似的输出时,表示已经启动成功
about to fork child process, waiting until server is ready for connections.
forked process: 84036
child process started successfully, parent exiting
如果需要关闭服务的话,可以先找出对应的进程 ID
$ ps aux | grep mongod
kevinbai 91637 0.1 0.2 5598860 29680 ?? S 7:37上午 0:01.52 mongod --dbpath data --logpath mongod.log --bind_ip=127.0.0.1 --port=27017 --fork
然后使用 kill 命令将其杀掉
$ kill 91637
如果是 Windows 平台,可能要在服务中找到 mongod 然后将其停止,不清楚的话可以百度/谷歌找下方法。
如果你觉得这样关闭比较麻烦,你可以启动时不指定 --fork
参数,这样 mongod 就会在前台运行,需要停止的时候使用快捷键 Ctrl
+ C
就可以了。不过这种方式有个弊端,就是不能关闭终端,否则 mongod 就停止运行了。
本节目的是为了快速搭建好 MongoDB 服务,方便进行后续的实验,所以只要启动没问题就行,至于其它的启动参数或者配置在之后的文章中才会有涉及。
2 MongoDB shell 使用
mongo 是一个命令行客户端工具,你可以将其类比成 Compass,但是没有用户界面,只能使用命令与服务端进行交互,一般将其叫做 MongoDB shell。
2.1 安装
如果你使用的本地安装 MongoDB 的方式,那么 mongo 工具已经安装好了,使用下面的命令确定下
$ mongo --version
如果输出类似这样
MongoDB shell version v4.2.8
git version: 43d25964249164d76d5e04dd6cf38f6111e21f5f
allocator: system
modules: none
build environment:
distarch: x86_64
target_arch: x86_64
说明已经 OK。
如果没有安装可以参考 1.2 节的 MongoDB 安装。有的平台是直接提供这个工具安装的,比如
如果你不需要使用 mongod 等其它程序,可以不用下载整个压缩包,直接使用这个。
2.2 连接服务器
如果你的服务器可以使用 IP 127.0.0.1 和端口 27017 访问的话,直接敲入 mongo 命令即可
$ mongo
如果 IP 或者端口有变化的话,可以另外指定
$ mongo --host 127.0.0.1 --port 27017
其中
--host
指定要访问的主机,可以是 IP 或者域名--port
指定要访问的端口
如果你觉得这样输入比较麻烦的话,可以使用下面的方式输入
$ mongo 127.0.0.1:27017/test1
我将上面 mongo 命令后的文本叫做地址串吧,地址串分为 3 个部分
- 主机,比如上面的 127.0.0.1
- 端口,比如上面的 27017
- 数据库,比如上面的 test1,不指定的话,默认是 test
上面的命令在登陆服务器的同时使用数据库 test1。再看几个例子
# 只指定主机(这里 # 指该行为注释)
$ mongo 127.0.0.1
# 只指定数据库
$ mongo test1
# 只指定主机和端口
$ mongo 127.0.0.1:27017
需要注意的是 mongo 可以只跟主机或者数据库,mongo 会自动识别。
如果你需要在地址串的基础上额外指定一些设置,你可以使用连接串,比如
$ mongo "mongodb://127.0.0.1:27017/test1?retryWrites=true"
其中
mongodb://
,用来标识这是一个 MongoDB 连接串的前缀,不用理解它,知道它是 MongoDB 规定的一种格式就行127.0.0.1
,主机27017
,端口test1
,数据库retryWrites=true
,表示开启 retryWrites 设置(retryWrites 后续文章会涉及,这里先不展开),设置必须放在问号(?
)后面,如果要指定多个设置,以与符号(&
)连接
你也可以使用 mongo 命令的 --retryWrites
选项指定
$ mongo 127.0.0.1:27017/test1 --retryWrites
具体使用哪一种可以根据自己的喜好,我个人比较喜欢使用地址串,如果需要指定额外的设置用连接串,如果有些设置只有 mongo 命令选项才有,再另外指定这些选项。
如果你需要比较全面的了解 mongo 命令行能够接收的参数,可以使用 --help
选项
$ mongo --help
2.3 简单使用
连接成功后会进入 mongo 交互式环境,如果你看到鼠标光标前面有个大于(>
)符号说明已经连接成功,本小节的操作都是在这个环境中进行。
查看当前有哪些数据库
// 在交互式环境中以双斜杠开头的文字表示注释
// 前面有大于符号的是命令,没有的是操作回显
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
使用某个数据库
> use admin
switched to db admin
查看自己在哪个数据库
> db
admin
显示有哪些集合
> show collections
system.version
怎么新建一个数据库呢?不用手动创建,当你 use 一个不存在的数据库并在里面新建了集合,这个库就存在了。比如我们创建个 test 数据库
> use test
switched to db test
这个时候库里没有集合,所以并没有新建该库
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
怎么创建集合呢?我们也可以不用手动创建,当你给一个不存在的集合插入文档后,这个集合就新建了
> db.student.insertMany([
... {'name': 'xiaoming', 'age': NumberInt(18)},
... {'name': 'xiaoli', 'age': NumberInt(19)},
... {'name': 'xiaogang', 'age': NumberInt(19)},
... ])
{
"acknowledged" : true,
"insertedIds" : [
ObjectId("5f274cd0934e0d8e38e097ce"),
ObjectId("5f274cd0934e0d8e38e097cf"),
ObjectId("5f274cd0934e0d8e38e097d0")
]
}
这里我们使用集合 test.student 的 insertMany 方法插入了 3 条数据。
说明下,mongo 中的命令是可以写成多行的,这种情况下每行前面有三个点号(...
)提示。
这个时候如果我们查看有哪些数据库,就可以看到 test 了,你可以自己试下。
使用 find 查看集合中有哪些文档
> db.student.find()
{ "_id" : ObjectId("5f274cd0934e0d8e38e097ce"), "name" : "xiaoming", "age" : 18 }
{ "_id" : ObjectId("5f274cd0934e0d8e38e097cf"), "name" : "xiaoli", "age" : 19 }
{ "_id" : ObjectId("5f274cd0934e0d8e38e097d0"), "name" : "xiaogang", "age" : 19 }
可以加上条件
// 查询 name 为 xiaoming 的学生
> db.student.find({'name': 'xiaoming'})
{ "_id" : ObjectId("5f274cd0934e0d8e38e097ce"), "name" : "xiaoming", "age" : 18 }
// 查询年龄大于 18 的学生
> db.student.find({'age': {$gt: 18}})
{ "_id" : ObjectId("5f274cd0934e0d8e38e097cf"), "name" : "xiaoli", "age" : 19 }
{ "_id" : ObjectId("5f274cd0934e0d8e38e097d0"), "name" : "xiaogang", "age" : 19 }
使用 update 更新文档
// 修改 name 为 xiaogang 的 age 为 20
> db.student.update({'name': 'xiaogang'}, {'$set': {'age':NumberInt(20)}})
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
使用 remove 删除文档
// 删除 name 为 xiaogang 的文档
> db.student.remove({'name': 'xiaogang'})
WriteResult({ "nRemoved" : 1 })
使用 drop 删除集合
> db.student.drop()
如果要退出交互式环境,可以这样
> exit
bye
也可以直接使用快捷键 Ctrl
+ C
。
2.4 JavaScript 解释器
mongo 其实是一个功能完备的 JavaScript 解释器。
在交互式环境中使用 JS
mongo 命令行中可以使用 JS 的标准库,也可以自定义函数。比如
// 使用 JSON 库
> JSON.stringify({'name': 'xiaoming', 'age': 18})
{"name":"xiaoming","age":18}
// 自定义函数并使用
> function print_hello() {
... print('hello')
... }
> print_hello()
hello
>
很多同学刚开始接触 mongo 时都容易忽略这一点,了解到这点后我们可以直接在命令行中编写简单的脚本,在进行一些简单的数据处理时可以提高效率。
执行 JS 文件
mongo 也可以执行 JS 文件,利用这一点我们可以把一些数据处理逻辑放在 JS 文件里,比如集合初始化等。举个例子,我们在某个目录新建文件 init_test_student.js
db = connect('127.0.0.1:27017/test');
var count = db.student.count()
if (count == 0) {
db.student.insertMany([
{"name" : "xiaoming", "age" : NumberInt(18)},
{"name" : "xiaoli", "age" : NumberInt(19)},
{"name" : "xiaogang", "age" : NumberInt(19) }
])
print('Collection test.student inited')
}
然后在该目录下执行
$ mongo init_test_student.js
如果集合 test.student 没有数据的话,就会插入 3 个文档。
如果你需要在执行完文件后停留在交互式环境,可以额外指定 --shell
参数
$ mongo init_test_student.js --shell
另外,直接在交互式环境中加载某个 JS 文件,也是可以的
// 如果 init_test_student.js 不在当前目录
// 你需要指定完整路径
> load('init_test_student.js')
需要注意的是,交互式环境中的有些语句是不能使用在 JS 文件中的,这些语句是 mongo 为了方便大家操作而扩展的。比如
use
不过有等效的 JS 语句
db = db.getSiblingDB('')
完整的列表可以查看官方文档(参考链接 2)
.mongorc.js
mongo 在进入交互式环境之前会先加载文件 .mongorc.js
并执行(如果存在的话),该文件可以存在于两个位置:/etc
和 ~
目录,前者是系统级别,后者用户级别,前者先于后者执行。使用 .mongorc.js
,我们可以在进行交互式环境之前做一些初始化工作。比如设置默认的数据库,先新建 ~/.mongorc.js
db = connect('127.0.0.1:27017/default')
保存后重新进入交互式环境
$ mongo
> db
default
可以看到设置已经生效。
如果你使用 mongo 执行 JS 文件的话,.mongorc.js
会在 JS 文件执行完毕后执行。
如果你不想加载 .mongorc.js
,可以指定 --norc
$ mongo --norc
2.5 使用编辑器编辑变量
在交互式环境中敲命令的时候,特别是一些多行的命令,直接敲不大方便,敲错了还不好修改,我们可以将这个操作转移到编辑器中进行。
比如我们要定义一个函数 print_hello
function print_hello() {
print('hello')
}
首先在交互式环境中设置编辑器路径
// 根据你的实际情况设置
> EDITOR = '/usr/bin/vim'
然后定义函数
> function print_hello() {}
之后敲入命令
> edit print_hello
这样就会跳转到编辑器进行编辑了。
需要注意的是,edit 后面只能跟变量(函数名也是可以的),也就是说在编辑某行命令的时候,我们都得先将其赋值给一个变量。
如果你使用这个功能比较频繁,可以将 EDITOR 的初始化语句放到 .mongorc.js
中,这样就不用每次手动设置了。
2.6 MongoDB shell 中的数据类型
之前的文章不是已经介绍了 MongoDB 中的数据类型了吗,怎么现在又来个 MongoDB shell 中的数据类型?其实不管你是什么语言的驱动,你都需要语言本身或者通过自定义数据类型的方式有个类型与 MongoDB 中的数据类型相对应。
以 MongoDB shell 来说,它是一个 JS 解释器,JS 中的数组可以与 MongoDB 中的数组对应,但有的类型 JS 本身没有,是 MongoDB shell 扩展出来的,比如 NumberInt 对应 MongoDB 中的 32 位整数,OjbectId 对应 MongoDB 中的 ObjectId。
以 Python 来说,语言自带的 list 类型可以对应 MongoDB 中的数组,有的类型原生并不支持,比如 ObjectId,所以它需要使用 pymongo 包来扩展自己的类型以对应 MongoDB 中的类型。
MongoDB shell 或者是其它语言的驱动包具体有或者扩展了哪些数据类型,建议参考官方文档,MongoDB shell 的可以参考链接 3。
3 小结
本文先介绍了 MongoDB 的简单安装,然后介绍了 MongoDB shell 的简单使用以及一些特性。后续的文章中我们主要使用的客户端工具是 MongoDB shell,然后 Compass 会搭配着用,希望大家可以多了解下这 2 个工具。
4 参考链接
- https://docs.atlas.mongodb.com/getting-started/
- https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/#differences-between-interactive-and-scripted-mongo
- https://docs.mongodb.com/v4.2/core/shell-types/