MongoDB

#认识 MongoDB

#基本概念

#什么是 MongoDB

一个以 json 为数据模型的文档数据库;文档来自于 “JSON Document”,并非我们理解的 PDF、word 文档;类似于 Oracle、MySQL 海量数据处理,数据平台

#MongoDB 是免费的吗?

#主要特点

#MongoDB 与关系型数据库

MongoDB RDBMS
数据模型\ 文档模型 关系模型
数据库类型\ OLTP OLTP
CRUD 操作\ MQL/SQL SQL
高可用\ 复制集 集群模式
横向扩展\ 通过原生分片完善支持 数据分区或者应用侵入式
索引支持\ B-树、全文索引、地理位置索引、多键(multikey)索引、TTL 索引 B 树
开发难度\ 容易 困难
数据容量\ 理论上没有上限 千万、亿
扩展方式\ 垂直扩展 + 水平扩展 垂直扩展

#MongoDB 的优势及特点

image.png

image.png

image.png

image.png

image.png

image.png

#安装 MongoDB 官网(opens new window)

#使用 dockerfile 模式安装 mongo

version: '3.1'

services:
mongo:
image: mongo
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: root
MONGO_INITDB_ROOT_PASSWORD: example
ports:
- 27001:27017 # 将MongoDB的默认端口映射到宿主机的27001端口上来
volumes: # 数据持久化配置
- /home/mongotest:/data/db # 将容器内部的数据映射到宿主机的home文件夹的mongotest文件夹里

以我的的服务为例,在 home 文件夹下创建一个 mongotest 文件,然后在里面创建一个 docker-compose.yml,然后将上面的内容复制到 docker-compose.yml 文件中(当然也可以使用 ftp 工具上传)

我这儿就用 vim 编辑 docker-compose.yml 文件

// 目录已经在/home/mongotest下
$ vim docker-compose.yml

然后就将内容复制进去,按ESC,然后在分别按:wq回车

image.png

#启动mongo服务

现在就可以使用docker-compose up -d来启动 mongo 服务了,执行命令后 docker 就去拉去 mongo 镜像并创建 mongo 数据

image.png

#查看运行进程

可以使用docker ps -a或者docker-compose查看现在已启动的 docker 镜像

image.png

#配置开放端口

连接前一定要检查宿主机端口是否开放,centOS 可以使用firewall-cmd --add-port=27017/tcp --permanent命令添加端口,添加完成后,重启安全组,命令:firewall-cmd --reload

image.png

如果在添加规则的时候出现如下报错的话,可有一下方案解决

image.png

$ rpm -qa firwalld // 回车后如果没有打印出任何东西,则表明没有安装
$ yum install firewalld

image.png

#创建用户并分配权限

参考官方文档(opens new window)

#角色说明

以下是MongoDB中内置的角色:

#数据库用户角色(Database User Roles) - 常用

read角色包含读取所有非系统集合数据和订阅部分系统集合(system.indexes、system.js、system.namespaces)的权限。

该角色权限包含命令操作:changeStream、collStats、dbHash、dbStats、find、killCursors、listIndexes、listCollections。

readWrite角色包含read角色的权限同时增加了对非系统集合数据的修改权限,但只对系统集合system.js有修改权限。

该角色权限包含命令操作:collStats、convertToCapped、createCollection、dbHash、dbStats、dropCollection、createIndex、dropIndex、find、insert、killCursors、listIndexes、listCollections、remove、renameCollectionSameDB、update。

#数据库管理角色(Database Administration Roles) - 常用

dbAdmin角色包含执行某些管理任务(与schema相关、索引、收集统计信息)的权限,该角色不包含用户和角色管理的权限。

对于系统集合(system.indexes、system.namespaces、system.profile)包含命令操作:collStats、dbHash、dbStats、find、killCursors、listIndexes、listCollections、dropCollection and createCollection(仅适用system.profile)

对于非系统集合包含命令操作:bypassDocumentValidation、collMod、collStats、compact、convertToCapped、createCollection、createIndex、dbStats、dropCollection、dropDatabase、dropIndex、enableProfiler、reIndex、renameCollectionSameDB、repairDatabase、storageDetails、validate

dbOwner角色包含对数据所有的管理操作权限。即包含角色readWrite、dbAdmin和userAdmin的权限。

userAdmin角色包含对当前数据库创建和修改角色和用户的权限。该角色允许向其它任何用户(包括自身)授予任何权限,所以这个角色也提供间接对超级用户(root)的访问权限,如果限定在admin数据中,也包括集群管理的权限。

该角色权限包含命令操作:changeCustomData、changePassword、createRole、createUser、dropRole、dropUser、grantRole、revokeRole、setAuthenticationRestriction、viewRole、viewUser。

#集群管理角色(Cluster Administration Roles)**

clusterManager角色包含对集群监控和管理操作的权限。拥有此角色的用户能够访问集群中的config数据库和local数据库。

对于整个集群该角色包含命令操作:addShard、appendOplogNote、applicationMessage、cleanupOrphaned、flushRouterConfig、listSessions (3.6新增)、listShards、removeShard、replSetConfigure、replSetGetConfig、replSetGetStatus、replSetStateChange、resync。

对于集群中所有的数据库包含命令操作:enableSharding、moveChunk、splitChunk、splitVector。

对于集群中config数据库和local数据库包含的命令操作可以参考官方文档:https://docs.mongodb.com/manual/reference/built-in-roles/#clusterManager (opens new window)

clusterMonitor角色包含针对监控工具具有只读操作的权限。如工具MongoDB Cloud Manager和工具Ops Manager

对于整个集群该角色包含命令操作:checkFreeMonitoringStatus(4.0新增)、connPoolStats、getCmdLineOpts、getLog、getParameter、getShardMap、hostInfo、inprog、listDatabases、listSessions (3.6新增)、listShards、netstat、replSetGetConfig、replSetGetStatus、serverStatus、setFreeMonitoring (4.0新增)、shardingState、top。

对于集群中所有的数据为包含命令操作:collStats、dbStats、getShardVersion、indexStats、useUUID(3.6新增)。

对于集群中config数据库和local数据库包含的命令操作可以参考官方文档:https://docs.mongodb.com/manual/reference/built-in-roles/#clusterMonitor (opens new window)

hostManager角色包含针对数据库服务器的监控和管理操作权限。

对于整个集群该角色包含命令操作:applicationMessage、closeAllDatabases、connPoolSync、cpuProfiler、flushRouterConfig、fsync、invalidateUserCache、killAnyCursor (4.0新增)、killAnySession (3.6新增)、killop、logRotate、resync、setParameter、shutdown、touch、unlock。

对于集群中所有的数据库包含命令操作:killCursors、repairDatabase。

clusterAdmin角色包含MongoDB集群管理最高的操作权限。该角色包含clusterManagerclusterMonitorhostManager三个角色的所有权限,并且还拥有dropDatabase操作命令的权限。

#备份和恢复角色(Backup and Restoration Roles) - 常用

backup角色包含备份MongoDB数据最小的权限。

对于MongoDB中所有的数据库资源包含命令操作:listDatabases、listCollections、listIndexes。

对于整个集群包含命令操作:appendOplogNote、getParameter、listDatabases。

对于以下数据库资源提供find操作权限:

  1. 对于集群中的所有非系统集合,包括自身的config数据库和local数据库;
  2. 对于集群中的系统集合:system.indexes、system.namespaces、system.js和system.profile;
  3. admin数据库中的集合:admin.system.users和admin.system.roles;
  4. config.settings集合;
  5. 2.6版本之前的system.users集合。

对于config.setting集合还有insert和update操作权限。

restore角色包含从备份文件中还原恢复MongoDB数据(除了system.profile集合)的权限。

restore角色有以下注意事项:

  1. 如果备份中包含system.profile集合而恢复目标数据库没有system.profile集合,mongorestore会尝试重建该集合。因此执行用户需要有额外针对system.profile集合的createCollection和convertToCapped操作权限;
  2. 如果执行mongorestore命令时指定选项--oplogReplay,则restore角色包含的权限无法进行重放oplog。如果需要进行重放oplog,则需要只对执行mongorestore的用户授予包含对实例中任何资源具有任何权限的自定义角色。

对于整个集群包含命令操作:getParameter。

对于所有非系统集合包含命令操作:bypassDocumentValidation、changeCustomData、changePassword、collMod、convertToCapped、createCollection、createIndex、createRole、createUser、dropCollection、dropRole、dropUser、grantRole、insert、revokeRole、viewRole、viewUser。

关于restore角色包含其它的命令操作可以参考官方文档:https://docs.mongodb.com/manual/reference/built-in-roles/#restore (opens new window)

#全数据库级角色(All-Database Roles)

以下角色只存在于admin数据库,并且适用于除了config和local之外所有的数据库。

readAnyDatabase角色包含对除了config和local之外所有数据库的只读权限。同时对于整个集群包含listDatabases命令操作。

在MongoDB3.4版本之前,该角色包含对config和local数据库的读取权限。当前版本如果需要对这两个数据库进行读取,则需要在admin数据库授予用户对这两个数据库的read角色。

readWriteAnyDatabase角色包含对除了config和local之外所有数据库的读写权限。同时对于整个集群包含listDatabases命令操作。

在MongoDB3.4版本之前,该角色包含对config和local数据库的读写权限。当前版本如果需要对这两个数据库进行读写,则需要在admin数据库授予用户对这两个数据库的readWrite角色。

userAdminAnyDatabase角色包含类似于userAdmin角色对于所有数据库的用户管理权限,除了config数据库和local数据库。

对于集群包含命令操作:authSchemaUpgrade、invalidateUserCache、listDatabases。

对于系统集合admin.system.users和admin.system.roles包含命令操作:collStats、dbHash、dbStats、find、killCursors、planCacheRead、createIndex、dropIndex。

该角色不会限制用户授予权限的操作,因此,拥有角色的用户也有可能授予超过角色范围内的权限给自己或其它用户,也可以使自己成为超级用户,userAdminAnyDatabase角色也可以认为是MongoDB中的超级用户角色。

dbAdminAnyDatabase角色包含类似于dbAdmin角色对于所有数据库管理权限,除了config数据库和local数据库。同时对于整个集群包含listDatabases命令操作。

在MongoDB3.4版本之前,该角色包含对config和local数据库的管理权限。当前版本如果需要对这两个数据库进行管理,则需要在admin数据库授予用户对这两个数据库的dbAdmin角色。

#超级用户角色(Superuser Roles)

WARNING

慎用

以下角色包含在任何数据库授予任何用户任何权限的权限。这意味着用户如果有以下角色之一可以为自己在任何数据库授予任何权限。

以下角色包含数据库所有资源的所有操作权限。

root角色包含角色readWriteAnyDatabase、dbAdminAnyDatabase、userAdminAnyDatabase、clusterAdmin、restore和backup联合之后所有的权限。

#内部角色(Internal Role)

MongoDB将此角色授予代表集群成员的用户对象,如副本集(replica set)成员或mongos实例。该角色允许用户对于需要的数据库操作都具有相应的权限,不要将该角色授予应用程序用户或其它管理员用户。

#总结说明

通过以上对内置角色的说明,总结一下较为常用的内置角色,如下表:

角色 权限描述
read 可以读取指定数据库中任何数据。
readWrite 可以读写指定数据库中任何数据,包括创建、重命名、删除集合。
readAnyDatabase 可以读取所有数据库中任何数据(除了数据库config和local之外)。
readWriteAnyDatabase 可以读写所有数据库中任何数据(除了数据库config和local之外)。
dbAdmin 可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。
dbAdminAnyDatabase 可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作(除了数据库config和local之外)。
clusterAdmin 可以对整个集群或数据库系统进行管理操作。
userAdmin 可以在指定数据库创建和修改用户。
userAdminAnyDatabase 可以在指定数据库创建和修改用户(除了数据库config和local之外)。

#创建自定义角色

#查看环境

TIP

这里要注意imooc用户是imooc数据库的imooc角色

> show dbs;
admin 0.000GB
config 0.000GB
imooc 0.001GB
local 0.000GB

> use imooc;
switched to db imooc

目前的权限情况

> db.createRole(
{
role: "imooc",
privileges: [
{ resource: { db: "imooc", collection: "users" }, actions: ["find", "update"] },
{ resource: { db: "imooc", collection: "rights" }, actions: ["find"] },
],
roles: []
}
)



> db.adminCommand(
{
createRole: "imooc",
privileges: [
{ resource: { db: "imooc", collection: "users" }, actions: ["find", "update"] },
{ resource: { db: "imooc", collection: "rights" }, actions: ["find"] }
],
roles: []
}

#查看自定义的角色

> db.getRole("imooc", { showPrivileges: true })

// 或

> db.getRoles({ rolesInfo: 1, showPrivileges: true })

// 或

> use admin
> db.runCommand(
{
rolesInfo: { role: "imooc", db: "admin" },
showPrivileges: true
}
)

#更新自定义的角色

为自定义角色imooc更新集合imooc.rights的insert权限。

> db.updateRole(
"imooc",
{
privileges: [
{ resource: { db: "imooc", collection: "users" }, actions: ["find", "update"] },
{ resource: { db: "imooc", collection: "rights" }, actions: ["find", "insert"] }
],
roles: []
}
)

// 或

> db.adminCommand(
{
updateRole: "imooc",
privileges: [
{ resource: { db: "imooc", collection: "users" }, actions: ["find", "update"] },
{ resource: { db: "imooc", collection: "rights" }, actions: ["find", "insert"] }
],
roles: []
}
)

#添加角色权限

为自定义角色imooc添加集合imooc.rights的remove权限。

db.grantPrivilegesToRole(
"imooc",
[
{ resource: { db: "imooc", collection: "rights" }, actions: ["remove"] }
]
)

// 或

> use admin
> db.runCommand(
{
grantPrivilegesToRole: "imooc",
privileges: [
{ resource: { db: "imooc", collection: "rights" }, actions: ["remove"] }
]
}
)

#删除角色

为自定义角色imooc收回集合imooc.users的update权限。

> db.revokePrivilegesFromRole(
"imooc",
[
{ resource: { db: "imooc", collection: "users" }, actions: ["update"] }
]
)



> use admin
> db.runCommand(
{
revokePrivilegesFromRole: "imooc",
privileges: [
{ resource: { db: "imooc", collection: "users" }, actions: ["update"] }
]
}
)

#创建用户并分配角色

use imooc

db.createUser(
{
user: "admin",
pwd: "123456",
roles: [ { role: "dbOwner", db: "imooc" } ]
}
)

#查看用户信息

> use imooc
> db.getUser("admin", { showPrivileges: true })

// 或

> db.getSiblingDB("imooc").runCommand(
{
usersInfo: "admin",
showPrivileges: true

}
)

#为用户添加角色

> use imooc
> db.grantRolesToUser(
"admin",
[
{ role: "dbOwner", db: "imooc" }
]
)

// 或

> use imooc
> db.runCommand(
{
grantRolesToUser: "admin",
roles:
[
{ role: "dbOwner", db: "imooc" }
]
}
)

#删除用户

> use imooc
> db.dropUser("admin")

#更改用户密码

> use imooc
> db.changeUserPassword("admin", "long-random-password")

#开启MongoDB的访问控制

要开启访问控制,则需要在mongod进程启动时加上选项--auth或在启动配置文件加入选项auth=true,并重启mongodb实例(使用docker开启的同学不用管)

## mongod配置文件如下
# cat mongodb.cnf
journal=true
dbpath=/data/mongodb/4.0/data
directoryperdb=true
fork=true
port=27017
logpath=/data/mongodb/4.0/logs/mongodb.log
quiet=true
bind_ip_all=true
auth=true

## 启动mongodb实例
# mongod -f mongodb.cnf
about to fork child process, waiting until server is ready for connections.
forked process: 44347
child process started successfully, parent exiting

#MongoDB交互终端

#直装方式

登录MongoDB实例

使用mongo shell登录mongodb实例:

 mongod --port 27017 --dbpath /data/db1

// 或者
// 更常用
mongo --port 27017

// 鉴权方式一登录
mongo --port 27017 -u "adminUser" -p "adminPass" --authenticationDatabase "admin"

// 鉴权方式二登录
mongo --port 27017

use admin
db.auth("adminUser", "adminPass")

打印:

MongoDB shell version v4.2.1
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("908acb35-1053-4287-85bc-83d89daec400") }
MongoDB server version: 4.2.1
Welcome to the MongoDB shell.

// 如果没有开启访问控制,则在登录时会提示如下警告信息
** WARNING: Access control is not enabled for the database.
** Read and write access to data and configuration is unrestricted.

#docker方式

交互式终端命令

$ docker exec -it <容器名称> 镜像名称
$ docker ps | grep mongo

image.png

docker 中连接 mongo

image.png

image.png

image.png

image.png

# 切换数据库
use admin

# 创建账号密码
db.createUser({user: "Forest", pwd: "123456", roles: [{role: "dbOwner", db: "test"}]})

image.png

上列图示环境

#基本操作

#数据库相关

#查看已有的数据库

$ show dbs

image.png

#查看当前数据库

$ db

image.png

#创建数据库或者切换数据库

// 如果有这个数据库的话就是切换,没有的话就是创建并切换
$ use <数据库名>

image.png

#查看当前数据库已有文档(表)

$ show collections

image.png

#删除数据库 dropDatabase

// 可以使用 db 命令来查看当前所在数据库
db.dropDatabase() // 删除当前库 这一句命令下去就删除了整个数据库

#增删改查CURD操作

#添加数据

语法\

// 添加单条数据
$ db.<collection>.insertOne(<JSON>)

// 添加多条数据
$ db.<collection>.insertMany([<JSON 1>, <JSON 2>, ..., <JSON n>])

image.png

image.png

#查看文档模型中的数据

  • find()是 MongoDB 数据库查询数据的基本指令,相当于 SQL 中的 SELECT
  • find()返回游标

查询条件对照表

逻辑运算符\ MongoDB 中的写法\
a 等于 1 { a : 1 }
a 不等于 1 { a : { $ne : 1 } }
a 大于 1 { a : { $gt: 1 } }
a 小于 1 { a : { $lt : 1 } }
a 大于等于 1 { a : { $gte : 1 } }
a 小于等于 1 { a : { $lte : 1 } }
a 等于 1 和 b 等于 1 { a : 1, b : 1 }或者{ $and: [{ a : 1 }, { b : 1 }] }
a 等于 1 或者 b 等于 1 { $or: [{ a : 1 }, { b : 1 }] }
判断 a 字段不存在 { a : { $exists : false } }
a 包含 1, 2, 3 { a : { $in : [1, 2, 3] } }

查询的逻辑运算符

#find 搜索子文档

find 支持使用“field.sub_field”的形式查询子文档。假设有一个文档:

db.fruit.insertOne({
name: 'apple',
from: {
country: 'China',
province: 'Chengdu'
}
})

db.fruit.find({ 'fruit.country': 'China' })
db.fruit.find({ from: { country: 'China' } }) // 等同于上一行语句

#使用 find 搜索数组

db.fruit.insert([
{ name: 'Apple', color: ['red', 'green'] },
{ name: 'mango', color: ['yellow', 'green'] }
])

// 查询
db.fruit.find({ color: 'red' }) // 查询颜色为'red'的所有数据

db.fruit.find({ $or: [{ color: 'red' }, { color: green }] }) // 查询颜色为'red'或者为'green'的所有数据

db.movies.insertOne({
title: 'Raiders of the Lost Ark',
filming_locations: [
{ city: 'Los Angeles', state: 'CA', country: 'USA' },
{ city: 'Rome', state: 'Lazio', country: 'Italy' },
{ city: 'Florence', state: 'SC', country: 'USA' }
]
})

// 查询城市为Rome的记录
db.movies.find({ 'filming_locations.city': 'Rome' })

子对象满足多个条件。考虑以下两个查询:

db.movies.find({
'filming_locations.city': 'Rome',
'filming_locations.country': 'USA'
})
db.movies.find({
filming_locations: {
$elemMatch: { city: 'Rome', country: 'USA' }
}
})

控制 find 返回的字段

db.movies.find({"category": "action"},{"\_id":0, title:1}); // \_id 不返回,title 返回

#删除数据

db.fruit.remove({ name: 'apple' }) // 删除所有name为apple的记录

db.fruit.remove({ weight: { $lt: 20 } }) // 删除所有weight小于20的记录

db.fruit.remove({}) // 删除所有记录

db.fruit.remove() // 不会删除任何东西,会报错

删除表

db.<集合名>.drop()  // db.fruit.drop()

#更新数据

image.png

TIP

参数说明

$ mongorestore -h localhost -u <用户名> -p <密码> --dir <备份文件夹>

#高级查询

#聚合查询

#什么是 MongoDB 聚合框架

MongoDB 聚合框架(Aggregation Framework)是一个计算框架,它可以:

  • 作用在一个集合或者几个集合上
  • 对集合的数据进行的一些列运算
  • 讲这些数据转化为期望的形式

从效果而言,聚合框架相当于 SQL 查询中的

#管道(Pipeline)和步骤(Stage)

image.png

pipeline = [$stage1, $stage2, ......, $stageN]

db.<COLLECTION>.aggregate(pipeline, { options })
步骤 作用 SQL 等价运算符
$match 过滤 WHERE
$project 投影 AS
$sort 排序 ORDER BY
$group 分组 GROUP BY
$skip/$limit 结果限制 SKIP/LIMIT
$looup 左外连接 LEFT OUTER JOIN
$unwind 展开数组 N/A
$graphLoopup 图搜索 N/A
$facet/$bucket 分页搜索 N/A

#聚合运算的使用场景

#MQL 常用步骤与 SQL 对比

image.png

image.png

#MQL 特有步骤$unwind

image.png

#MQL 特有的$bucket

image.png

#MQL 特有的$facet

image.png

image.png

#复制集

#复制集的作用

#典型复制集结构

image.png

#数据是如何复制的?

image.png

#选举时如何完成故障恢复的?

#影响选举的因素

#常见选项

image.png

#复制集注意事项

#Atlas-MongoDB 公有云托管服务

image.png