MongoDB

一、环境配置

2.1、Windows 平台

如果是 Windows 平台,MongoDB 提供了可用于 32 位和 64 位系统的预编译二进制,登录 MongoDB 官网并且下载安装包,然后一步一步的操作即可!

2.2、Linux 平台

生产环境基本都是 Linux 平台,为了和生产保持一致,这里采用的服务器是CentOS7,安装过程也比较简单!

创建资源文件

  1. sudo vim /etc/yum.repos.d/mongodb-org-4.0.repo

编辑内容如下

  1. [mongodb-org-4.0]
  2. name=MongoDB Repository
  3. baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/4.0/x86_64/
  4. gpgcheck=1
  5. enabled=1
  6. gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc

运行以下命令安装 mongodb

  1. sudo yum install -y mongodb-org

安装完成之后,配置mongod.conf允许远程连接

  1. #编辑mongod.conf
  2. vim /etc/mongod.conf
  3. #将net:bindIp: 127.0.0.1 改为 0.0.0.0
  4. net:
  5. bindIp:0.0.0.0

最后启动服务

  1. #开启服务
  2. systemctl start mongod
  3. #其他服务
  4. #关闭服务
  5. systemctl stop mongod
  6. #重启服务
  7. systemctl restart mongod
  8. #开机自启
  9. systemctl enable mongod

至此,环境配置已经完成!

二、数据库操作

MongoDB 的数据操作,是开发人员接触最频繁的部分,第一次使用的时候,可以发现它和传统使用的 sql 脚本命令完全不同,但是又类似,下面来深入的了解下!

2.1、进入 MongoDB

进入 MongoDB 服务很简单,输入如下命令即可进入!

  1. mongo

例如,在CentOS里面输入命令之后,进入的服务界面如下:
MongoDB使用总结 - 图1

2.2、创建数据库

MongoDB 创建数据库的语法格式如下:

  1. use DATABASE_NAME

:::tips 如果数据库不存在,则创建数据库,否则切换到指定数据库。 ::: 输入如下命令,可以查询数据库列表

  1. #查询数据库列表
  2. show dbs
  3. #命令输出结果:
  4. admin
  5. config
  6. local

可以看到,当前 MongoDB 有三个数据库!
输入如下命令,可以切换到admin数据库

  1. use admin

输入db命令,还可以查询当前数据库

  1. db

2.3、创建用户

默认的情况下,是没有用户的,也无法操作数据库,因此需要创建一个用户,同时给他分配权限!

2.3.1、创建一个管理员用户

创建一个用户、密码都是admin的用户,同时给这个用户分配userAdminAnyDatabase角色,指定的数据库为admin

  1. #创建一个admin用户
  2. db.createUser(
  3. {
  4. user: "admin",
  5. pwd: "admin",
  6. roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
  7. })

其中字段含义如下:

  • user:用户的名字;
  • pwd:用户的密码;
  • roles:指定用户的角色,可以用一个空数组给新用户设定空角色。
  • roles 中的 role:指定角色。
  • roles 中的 db:指定的数据库,例如上面中的角色userAdminAnyDatabase,只在 admin 数据库中可用。

角色在 MongoDB 中,代表着某个用户是否有权限访问数据库或者操作数据库,理解这点非常重要!
MongoDB 角色定义如下:

角色类型 名称 描述
admin数据库角色 readAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读权限
admin数据库角色 readWriteAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的读写权限
admin数据库角色 userAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的userAdmin权限
admin数据库角色 dbAdminAnyDatabase 只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限
admin数据库角色 clusterAdmin 只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限
admin数据库角色 root 只在admin数据库中可用,超级账号,超级权限
数据库管理角色 dbAdmin 允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问system.profile
数据库管理角色 userAdmin 允许用户向system.users集合写入,可以在指定数据库里创建、删除和管理用户
数据库用户角色 read 允许用户读取指定数据库
数据库用户角色 readWrite 允许用户读写指定数据库

2.3.2、创建一个不受访问限制的超级用户

如果想创建一个不受访问限制的超级用户,赋予root角色即可!

  1. #创建超级用户
  2. db.createUser(
  3. {
  4. user:"root",
  5. pwd:"root",
  6. roles:["root"]
  7. }
  8. )

2.3.3、创建一个业务数据库普通用户

如果想创建一个业务数据库普通用户,例如只能访问test_db数据库,并且只负责数据的増查改删。

  1. # 创建或者切换数据库到test_db
  2. use test_db
  3. # 创建一个test用户,并且只能访问test_db,对表只有读写权限
  4. db.createUser(
  5. {
  6. user: "test",
  7. pwd: "test",
  8. roles: [ { role: "readWrite", db: "test_db" } ]
  9. })

2.3.4、验证用户是否可以正常登录

对于刚刚创建的用户,验证它是否能正常登录!

  1. db.auth("test","test")

如果返回是1表示鉴权正常!

2.3.5、查询当前数据库用户信息

查询创建的用户,命令也很简单!

  1. # 查看创建的用户
  2. show users

2.3.6、修改用户密码

有些时候会忘记密码,可通过如下方式进行修改!

  1. #修改用户密码
  2. db.changeUserPassword("username", "xxxxx")

2.3.7、删除用户

如果某个用户需要停用,可通过如下方式进行删除

  1. #切换指定数据库
  2. use test_db
  3. #删除用户
  4. db.dropUser('test')

2.3.8、删除数据库

如果某个数据库需要停用,可通过如下方式进行删除(只有超级管理员有权限删除)

  1. #切换指定数据库
  2. use test_db
  3. #删除数据库
  4. db.dropDatabase()

2.4、创建集合

MongoDB 并无这个概念,而对应的定义叫:集合,在关系型数据库中看到的表数据,在 MongoDB 中被定义为:文档,MongoDB 也被很多人成为文档数据库
在关系型数据库中,表数据是一行一行的存储,但是在 MongoDB 中,可能不是这样,如果存储的 json 非常复杂,嵌套很深,那么在 MongoDB 中存储的行数,可能非常深,存储的时候类似在页面看到的父子表结构!

2.4.1、创建一个集合

MongoDB 中使用 createCollection() 方法来创建集合。
语法格式:

  1. db.createCollection(name, options)

参数说明:

  • name: 要创建的集合名称
  • options: 可选参数, 指定有关内存大小及索引的选项

例如,在 test_db 数据库中创建 tb_user 集合:

  1. # 切换到test_db数据库
  2. use test_db
  3. # 创建 tb_user 集合
  4. db.createCollection("tb_user")
  5. #输出结果
  6. { "ok" : 1 }

如果要查看已有的集合,可以使用show collections命令!

  1. show collections

下面是带有几个关键参数的createCollection()的用法,下面命令表示:创建固定集合tb_user,整个集合空间大小6142800KB, 文档最大个数为10000

  1. db.createCollection("tb_user", { capped : true, autoIndexId : true, size : 6142800, max : 10000 } )

在 MongoDB 中,很多时候不需要手动创建集合。当插入一个文档时,MongoDB 会自动创建集合!

  1. # 向集合tb_user 插入一条文档数据
  2. db.tb_user.insert({"name" : "张三"})
  3. #查询集合
  4. show collections
  5. # 输出结果
  6. tb_user

2.4.2、删除一个集合

MongoDB 中使用 drop() 方法来删除集合。
语法格式:

  1. db.collection.drop()

例如,删除在 test_db 数据库中 tb_user 集合:

  1. # 切换到test_db数据库
  2. use test_db
  3. # 创建 tb_user 集合
  4. db.tb_user.drop()
  5. #输出结果
  6. true

2.5、创建文档

创建文档,类似在关系型数据库中,将数据插入到数据库,操作也很简单!

2.5.1、插入文档

MongoDB 使用 insert()save() 方法向集合中插入文档。
语法如下:

  1. db.COLLECTION_NAME.insert(document)
  2. db.COLLECTION_NAME.save(document)
  • save():如果_id主键存在则更新数据,如果不存在就插入数据。
  • insert():若插入的数据主键已经存在,则会抛异常,提示主键重复,不保存当前数据。

例如,在test_db数据库的tb_user集合中,插入一条数据

  1. db.tb_user.insert(
  2. {
  3. name:"张三",
  4. age:18,
  5. gender:"男",
  6. tags: ['宅男', '技术控', '脱发严重']
  7. })

如果该集合不在该数据库中, MongoDB 会自动创建该集合并插入文档。
查看已插入文档,命令如下:

  1. #查询tb_user集合中的数据
  2. db.tb_user.find()
  3. # 输出结果
  4. { "_id" : ObjectId("6022310f6b5e964b0a5916e6"), "name" : "张三", "age" : 18, "gender" : "男", "tags" : [ "宅男", "技术控", "脱发严重" ] }

当然,还可以通过save()命令进行插入,如果不指定_id字段 save() 方法类似于 insert() 方法。如果指定 _id 字段,则会更新该 _id 的数据。
例如,将张三年龄更新到30岁!

  1. db.tb_user.save(
  2. {
  3. _id: ObjectId("6022310f6b5e964b0a5916e6"),
  4. name:"张三",
  5. age:30,
  6. gender:"男",
  7. tags: ['宅男', '技术控', '脱发严重']
  8. })

查看文档

  1. db.tb_user.find()
  2. # 输出结果
  3. { "_id" : ObjectId("6022310f6b5e964b0a5916e6"), "name" : "张三", "age" : 30, "gender" : "男", "tags" : [ "宅男", "技术控", "脱发严重" ] }

2.5.2、更新文档

MongoDB 提供了 update()save() 方法来更新集合中的文档。
语法格式如下:

  1. db.collection.update(
  2. <query>,
  3. <update>,
  4. {
  5. upsert: <boolean>,
  6. multi: <boolean>,
  7. writeConcern: <document>
  8. }
  9. )
  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如inc…)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。

例如,将张三年龄更新到22岁!

  1. db.tb_user.update({'name':'张三'},{$set:{'age':22}})

查询已更新的数据

  1. db.tb_user.find()
  2. # 输出结果
  3. { "_id" : ObjectId("602235216b5e964b0a5916e8"), "name" : "张三", "age" : 22, "gender" : "男", "tags" : [ "宅男", "技术控", "脱发严重" ] }

以上语句只会修改第一条发现的文档,如果要修改多条相同的文档,则需要设置multi参数为true

  1. db.tb_user.update({'name':'张三'},{$set:{'age':22}},{multi:true})

2.5.3、删除文档

MongoDB 中的remove()函数是用来移除集合中的数据
语法格式如下:

  1. db.collection.remove(
  2. <query>,
  3. {
  4. justOne: <boolean>,
  5. writeConcern: <document>
  6. }
  7. )
  • query :(可选)删除的文档的条件。
  • justOne : (可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数,或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern :(可选)抛出异常的级别。

例如,删除姓名为张三的用户

  1. db.tb_user.remove({'name':'张三'})

查询数据是否被删除

  1. db.col.find()
  2. #结果为空

2.5.4、查询文档

MongoDB 查询文档使用 find() 方法。
语法格式如下:

  1. db.collection.find(query, projection)
  • query :可选,使用查询操作符指定查询条件
  • projection :可选,使用投影操作符指定返回的键。查询时返回文档中所有键值, 只需省略该参数即可(默认省略)。

如果需要以易读的方式来读取数据,可以使用 pretty() 方法,语法格式如下:

  1. db.col.find().pretty()

首先插入几条数据,插入结果如下:
MongoDB使用总结 - 图2
例如,查询一个性别为的用户信息

  1. #单个条件查询,类似 sql语句中的 gender = '男'
  2. db.tb_user.find({"gender":"男"})

查询一个性别为,姓名为张三的用户

  1. #多条件查询,类似 sql语句中的 gender = '男' and name = '李四'
  2. db.tb_user.find({"gender":"男","name":"李四"})

查询一个性别为 或者 姓名为张三的用户

  1. #多条件查询,类似 sql语句中的 gender = '男' or name = '李四'
  2. db.tb_user.find({$or:[{"gender":"男"},{"name": "李四"}]})

查询一个性别为 或者 姓名为张三,同时年龄大于30的用户

  1. #多条件查询,类似 sql语句中的 age > 30 and ( gender = '男' or name = '李四')
  2. db.tb_user.find({"age": {$gt:30}, $or:[{"gender":"男"},{"name": "李四"}]})

2.5.5、分页查询文档

如果需要分页查询集合数据,可以使用limit()skip()函数,其中limit()表示读几条数据,skip()表示从第几条数据开始。

  1. #从集合中的第三行数据开始,读2条数据返回
  2. db.tb_user.find({}).limit(2).skip(3)

2.5.6、文档排序

和关系型数据库一样,MongoDB 可以使用sort()方法进行排序,通过参数指定排序的字段,并使用 1-1 来指定排序的方式,其中 1 为升序排列,而 -1 是用于降序排列。
例如,查询tb_user文档,按照age进行升序排序!

  1. db.tb_user.find({}).sort({"age":1})

2.6、创建索引

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

2.6.1、创建索引

MongoDB 使用 createIndex() 方法来创建索引,语法格式如下:

  1. db.collection.createIndex(keys, options)

语法中 Key 值为要创建的索引字段,1 为指定按升序创建索引,如果想按降序来创建索引指定为 -1 即可!
例如,给tb_user文档中的age创建一个索引!

  1. db.tb_user.createIndex({"age":1})

创建索引是一个比较耗时的动作,还可以通过参数配置,在后台创建索引。

  1. db.tb_user.createIndex({"age":1}, {background: true})

通过在创建索引时加background:true的选项,让创建工作在后台执行!

2.6.2、查看索引

MongoDB 提供了getIndexes()方法,可以进行查看索引。
例如,查询tb_user集合中的索引

  1. db.tb_user.getIndexes()

2.6.3、删除索引

不在需要的索引,可以将其删除。删除索引时,可以删除集合中的某一索引,可以删除全部索引。
语法格式:

  1. db.COLLECTION_NAME.dropIndex("INDEX-NAME")

例如,删除集合tb_user集合中的age索引:

  1. #查询索引
  2. db.tb_user.getIndexes()
  3. #输出结果
  4. [
  5. {
  6. "v" : 2,
  7. "key" : {
  8. "_id" : 1
  9. },
  10. "name" : "_id_",
  11. "ns" : "test_db.tb_user"
  12. },
  13. {
  14. "v" : 2,
  15. "key" : {
  16. "age" : 1
  17. },
  18. "name" : "age_1",
  19. "ns" : "test_db.tb_user"
  20. }
  21. ]

删除对应的age_1索引!

  1. db.tb_user.dropIndex("age_1")

三、客户端

对于任何一款数据库,如果没有可视化界面操作,在开发的时候,可以说极其不方便,下面是一些常用的客户端。

Robo 3T(免费、轻量级) ,可以访问官网获取

MongoDB使用总结 - 图3

Studio 3T(全面,收费),访问官网地址获取

MongoDB使用总结 - 图4
Studio 3T整体的体验比Robo 3T要一点,两者功能都比较齐全!
在使用的时候,可以根据个人喜爱进行选择!

四、MongoDB的安全控制

网上很多 mongodb 被黑,使大家将目光投向了mongodb 的权限控制。
其实 mongodb 本身有一套完备的 RBAC 权限控制体系,这次被黑基本都是没有遵照 mongodb 的生产环境部署手册部署的结果。
平时玩一玩 mongodb 习惯了不设置用户名密码,当数据库放到公网时,由于也没有设置用户名密码,任何人都可以随便访问,而且由于没有开启授权访问,使得任何登录到 mongodb 服务器的用户都拥有最高权限!
一些居心不良的人发现,就可以把数据拷走,删除数据库,从而勒索赎金!
以上文CentOS7安装为例,修改/etc/mongod.conf,在security部分添加如下配置,开启授权访问!

  1. security:
  2. authorization: enabled

修改完成之后,重启 mongodb 服务

  1. #重启服务
  2. systemctl restart mongod