MongoDB数据库操作

1. MongoDB部署

1.1 基于Windows平台

1.1.1 下载MongoDB

  在Windows 64位系统中安装64位的MongoDB的安装包,通过访问MongoDB官网https://www.mongodb.com/download-center/community 进入MongoDB下载页面。

db09e338fa9d4938aec06cc37f0d7570.png

载MngoDB安装包下载MongoDB安装包

Version指定MongoDB版本,MongoDB的版本分为稳定版和开发板,本次安装使用稳定版4.2.2。

OS选择安装平台,本次安装选择Windows x64 x64。

Package选择安装包打包方式,MSI表示安装包,ZIP表示压缩包,本次安装选择ZIP。

Download下载选定的MongoDB安装包。

1.1.2 解压MongoDB安装包

90bf597a8f3543388c493b6cf1095f27.png

  MongoDB安装包下载完成后名称为mongodb-win32-x86_64-2012plus-4.2.2.zip,通过解压缩方式完成MongoDB的安装,解压后MongoDB的bin目录下存放了MongoDB相关程序。

a9f9f173d11c4a5fa2464104f0132380.png

1.1.3 启动MongoDB服务

1.1.3.1 使用命令行参数的方式启动

  • 创建文件夹data及子文件夹db和log,分别用于存放数据库文件和日志文件。

  • 在MongoDB的bin目录下打开命令行窗口。使用命令行参数的方式启动MongoDB服务。

  • 在命令行窗口执行:mongod --dbpath F:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.2\data\db --logpath F:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.2\data\logs\mongodb.log --logappend 命令启动MongoDB服务。

  • 命令行窗口的光标会一直闪动。查看日志文件mongodb.log,出现“MongoDB starting”,证明MongoDB启动成功。

4901db5e154040678f0d73b0580ef282.png

1.1.3.2 使用配置文件的方式启动

  • 在MongoDB目录下创建conf文件夹,在该目录下创建一个文件mongod.conf,用于指定数据库文件的存储路径、日志文件路径及MongoDB的相关配置信息。
  • 在配置文件mongod.conf中填写如下配置内容(或者下一页的配置内容)。
storage:
 dbPath: F:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.2\data\db
systemLog:
 destination: file
 path: F:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.2\data\logs\mongodb.log
 logAppend: true
  • 在MongoDB的bin目录下打开命令行窗口。
F:\MongoDB\mongodb-win32-x86_64-2012plus-4.2.2\bin
  • 在命令行窗口执行命令:mongod -f ..\conf\mongod.conf (或mongod --config ..\conf\mongod.conf)启动mongodb服务。

  • 日志文件出现 MongoDB starting ,证明MongoDB启动成功。

在配置文件mongod.conf中填写如下配置内容:

#数据库路径
dbpath=d:\MongoDB\Server\3.4\data

#日志输出文件路径
logpath=d:\MongoDB\Server\3.4\logs\mongo.log

#错误日志采用追加模式
logappend=true

#启用日志文件,默认启用
journal=true
#这个选项可以过滤掉一些无用的日志信息,若需要调试使用请设置为falsequiet=true

#端口号 默认为
27017port=27017

————————————————

原文链接:https://blog.csdn.net/qq_42498815/article/details/112967833

  • 安装和启动 MongoDB服务
  • 通过执行bin/mongod.exe,使用–install选项来安装服务,使用–config选项来指定之前创建的配置文件。
  • cmd进入d:\MongoDB\Server\3.4\bin
  • mongod.exe ‐‐config “d:\MongoDB\Server\3.4\mongo.conf” ‐‐install(若执行这条语句报服务名无效则卸载mongodb,重新安装)
  • 重新安装后执行:d:\MongoDB\Server\3.4\bin\mongod.exe --dbpath “d:\MongoDB\Server\3.4\data” --logpath “d:\MongoDB\Server\3.4\logs\mongo.log” --install --serviceName “MongoDB” --logappend –directoryperdb
  • 启动MongoDB服务: net start MongoDB
  • 关闭MongoDB服务 :net stop MongoDB
  • 移除MongoDB服务: “ d:\MongoDB\Server\3.4\bin\mongod.exe” ‐‐remove
  • 启动完成后,浏览器中输入http://127.0.0.1:27017看到如下界面即说明启动成功。

1.2.基于Linux平台

1.2.1 新建用户

  由于root用户拥有的权限很大,处于系统安全的考虑,需要新建一个普通用户操作MongoDB数据库,因此我们需要新建一个用户user_mongo。

  1. 打开Linux虚拟机并通过远程工具CRT连接Linux平台。
  2. 执行“ useradd user_mongo ”命令,新建用户user_mongo。
  3. 执行“ passwd user_mongo ”命令,初始化新用户user_mongo的密码。

1.2.2 用户授权

  1. 执行“ ls -l /etc/sudoers ”命令,查看文件sudoers的操作权限,默认为只读。
  2. 执行“ chmod -v u+w /etc/sudoers ”命令,将文件sudoers的权限修改为可编辑。
  3. 执行“ vi /etc/sudoers ”命令编辑sudoers文件,添加“user_mongo ALL=(ALL) ALL”内容。
  4. 按Esc键,执行 :wq 命令,保存退出文件sudoers。
  5. 执行“ chmod -v u-w /etc/sudoers ”命令,将该文件的权限改为默认只读权限。
  6. 执行“ su user_mongo ”切换到user_mongo用户,验证用户是否创建成功 。

87466759b24945bc9a9afc1c7f96b7c0.png

1.2.3 下载MongoDB安装包

  在Centos7 64位系统中安装64位的MongoDB的安装包,通过访问MongoDB官网https://www.mongodb.com/download-center/community进入MongoDB下载页面。

175027db7dd945a984e7dc1630a554c8.png

Version指定MongoDB版本,MongoDB的版本分为稳定版和开发板,本次安装使用稳定版4.2.2。

OS选择安装平台本次安装选择CentOS 7 64。

Package选择安装包打包方式,RPM表示安装包, TGZ表示压缩包,本次安装选择TGZ 。

Download下载选定的MongoDB安装包。

1.2.4 解压MongoDB安装包

  将MongoDB安装包(mongodb-linux-x86_64-rhel70-4.2.2.tgz)上传到Linux系统中通过解压缩的方式安装MongoDB。

  1. 打开Linux虚拟机并通过远程工具CRT连接Linux平台,使用user_mongo用户。
  2. 执行“sudo rz”命令上传文件命令将MongoDB安装包上传至Linux平台的/opt/software目录下。
  3. 执行“sudo chown -R user_mongo:user_mongo mongodb-linux-x86_64-rhel70-4.2.2.tgz”命令,将MongoDB安装包的用户和用户组权限修改为user_mongo。
  4. 执行“sudo chown -R user_mongo:user_mongo /opt/servers/mongodb_demo/”命令,将MongoDB解压后存放的目录mongodb_demo的用户和用户组权限修改为user_mongo。
  5. 执行“tar -zxvf mongodb-linux-x86_64-rhel70-4.2.2.tgz -C /opt/servers/mongodb_demo/”命令,将MongoDB安装包解压到指定目录/opt/servers/mongodb_demo/。
  6. 进入/opt/servers/mongodb_demo目录,执行“mv mongodb-linux-x86_64-rhel70-4.2.2 mongodb”命令,将MongoDB解压后的目录重命名为mongodb。

7546532bae974f8f93e9bf0bb2088911.png

e9dcb32a578b4aa6af7d841136bcbca8.png

68ba2dd23d6245f08363fae913cfa4f3.png

1.2.5 配置MongoDB

  通过解压缩的方式离线安装MongoDB,不会自动创建数据文件存放目录和日志存放目录,因此需要手动创建这两个目录。

  1. 打开Linux虚拟机并通过远程工具CRT连接Linux平台,使用user_mongo用户。
  2. 执行“mkdir -p standalone/data/db/”命令,创建数据文件存放目录。
  3. 执行“mkdir standalone/logs/”命令,创建日志文件存放目录。
  4. 执行“touch standalone/logs/mongologs.log”命令,创建日志文件。
  5. 执行“vi ~/.bash_profile”命令,编辑用户环境变量文件.bash_profile。
  6. 添加“export PATH=/opt/servers/mongodb_demo/mongodb/bin:$PATH ”内容,配置MongoDB用户环境变量。
  7. 保存并退出用户环境变量文件.bash_profile。
  8. 执行“source ~/.bash_profile”命令,初始化用户环境变量。

1.2.6 启动MongoDB服务

1.2.6.1 命令行参数方式

  • 打开Linux虚拟机并通过远程工具CRT连接Linux平台,使用user_mongo用户。
  • 执行命令,启动MongoDB服务。
mongod --dbpath=/opt/servers/mongodb_demo/standalone/data/db/ --logpath=/opt/servers/mongodb_demo/standalone/logs/mongologs.log --logappend --fork
# 这里的命令中间不能用回车键换行,每个短线前面只能有一个空格,每次都是两个短线在一起
  • 控制台出现“child process started successfully,parent exiting”,说明成功启动MongoDB服务。
  • 可执行“ ps -ef | grep mongod ”命令,查看启动的MongoDB进程号,执行“kill -2 进程号”命令,关闭MongoDB服务。

1.2.6.2 配置文件方式

  1. 在mongodb目录下执行“mkdir conf/”命令,创建配置文件目录。
  2. 在conf目录下执行“touch mongod.conf”命令,创建配置文件。
  3. 执行“ vi mongod.conf ”命令编辑配置文件,添加如下内容。
    systemLog:
      destination: file
      path: "/opt/servers/mongodb_demo/standalone/logs/mongologs.log"
      logAppend: true
    storage:
      dbPath: "/opt/servers/mongodb_demo/standalone/data/db/"
      journal:
        enabled: true
    processManagement:
      fork: true
  4. 保存退出配置文件后,执行命令,启动MongoDB服务。
mongod -f /opt/servers/mongodb_demo/mongodb/conf/mongod.conf

1.2.7 关闭MongoDB服务

  1. 执行“ ps -ef | grep mongod ”命令,查看启动的MongoDB的服务进程。
  2. 执行 “ kill -2 9670 ” 命令,结束MongoDB的服务进程(MongoDB的服务进程每次都不同,因此若想结束该进程,必须在命令中提供对应的MongDB进程号)。
  3. 执行“ ps -ef | grep mongod ”命令,查看MongoDB服务的进程是否存在。

1.2.8 Linux系统下MongoDB部署结构

准备工作1. 建好虚拟机,2. 配置SSH, 3. 在虚拟机上创建本教材用于存放相关软件安装包和服务的目录,如图

f444737f7ea54ba2bd39bcdacfce290e.png

4. 创建新用户:user_mongo并给新用户授权

MngoDB部署结构

2ec25111333f4c3baca57cf2b10f9f95.png

2. 数据库操作

  首先打开Linux虚拟机并通过远程工具CRT连接Linux平台,然后切换到user_mongo用户,执行“source ~/.bash_profile”命令,初始化用户环境变量,最后启动MongoDB服务,执行 mongo 命令,进入 mongo shell 中。

  Windows:

  • 在MongoDB的bin目录下打开命令行窗口。
  • 在命令行窗口执行命令:mongod -f ..\conf\mongod.conf --bind_ip_all(或mongod --config ..\conf\mongod.conf)启动mongodb服务。
  • 不要关闭启动后的命令行窗口,在bin目录中打开一个新的cmd窗口,执行mongo命令。

2.1 新建数据库

语法 :use DATEBASE_NAME             

【 use 数据库名 

  • use:用于切换/创建数据库,若不存在则创建,否则切换到指定数据库。
  • DATABASE_NAME:数据库名称。

eg:创建一个数据库,名称为articledb_137

36e1b5beb69e480fa15076e227b490d6.png

2.2 查看数据库

语法:① show dbs ② db

  • show dbs:查看所有数据库的名称和存储情况,dbs是databases的简称。

  • 执行“show dbs”命令,查看所有数据库。

  • use命令创建的数据库存储在内存中,若数据库中没有任何数据则 “ show dbs ” 命令无法查看use命令创建的articledb_137数据库。

  • db:表示当前数据库对象。

  • 执行“db”命令,查看当前数据库,需要先切换到指定数据库。

2.3 删除数据库

语法:db.dropDatabase()

  • db:表示当前数据库对象。
  • dropDatabase():用于删除当前数据库的方法。
  • 执行 “ db.dropDatabase() ” 命令,删除当前数据库,执行命令前应使用use命令切换到要删除的数据库,为了防止误删可执行命令db验证当前数据库是否为指定删除的数据库。

3. 集合操作

  首先打开Linux虚拟机并通过远程工具CRT连接Linux平台,然后切换到user_mongo用户,source ~/.bash_profile,最后启动MongoDB服务并进入mongo shell切换到articledb数据库。

3.1 创建集合

3.1.1 显示创建集合

语法:db.createCollection(COLLECTION_NAME,[OTIONS]) 

db.createCollection("集合名")

3.1.2 隐式创建集合

语法:db.COLLECTION_NAME.insert(DOCUMENT) 

【 db.集合名.insert(JSON数据) 】

  • db:表示当前数据库对象。
  • createCollection():创建集合方法。
  • COLLECTION_NAME:表示集合名称。
  • OPTIONS:表示集合配置。
  • DOCUMENT:表示文档。
  • insert():向集合中插入文档的方法。
  • 执行 “ db.createCollection("myCollection") ” 命令,显式创建集合myCollection。

eg:创建一个集合,名称为collection_137

c05b41871ffb46e197941be7180309e8.png

3.2 查看集合

语法:show colllections

3.3 删除集合

语法:db.COLLECTION_NAME.drop() 

db.集合名.drop()

  • db:表示当前数据库对象。
  • COLLECTION_NAME:表示集合名称。

  • drop():删除集合方法。

  • 执行“ db.collection.drop() ”命令,删除集合collection。

5fbcf753a6924d7186ed27f1bee2b6ca.png

4. 文档的插入、更新与删除操作

4.1 文档插入

4.1.1 单文档插入

语法:db.COLLECTION_NAME.insert({document})

db.集合名.insert({文档内容})

      db.COLLECTION_NAME.save({document})

db.集合名.save({文档内容})

  • db:当前数据库对象。

  • COLLECTION_NAME:当前集合对象。

  • insert()和save():插入单文档方法。

  • insert()和save()方法的区别:若使用insert()方法插入文档时,集合中已存在该文档,则会报错。若使用save()方法插入文档时,集合中已存在该文档,则会覆盖。

f5bfc9c450fb448b8ab6f8c22337f03c.png

4.1.2 多文档插入

语法:db.COLLECTION_NAME.insertMany([{document1},{document2},...])

db.集合名.insertMany({文档1},{文档2},...)

  • insertMany():插入多文档方法。

39b773d1985547058013897528e07f93.png

4.1.3 查看集合中的文档

语法:db.集合名.find()

eg:查看集合collection_137中的文档

4.2 文档更新

语法:db.COLLECTION_NAME.update(criteria,objNew,upsert,multi)       

db.集合名.update(条件,新数据[是否新增,是否修改多条])

  • db:当前数据库对象。

  • COLLECTION_NAME:当前集合对象。

  • update():更新文档方法。

  • criteria:更新的查询条件,类似sql中的where。

  • objNew:更新的对象和操作符,类似sql中的set。

  • upsert:不存在更新对象时,是否插入,默认为false。

  • multi:默认为false,只更新查找到的第一个文档,反之更新所有。

eg:将评论者爱德华的评论内容 content 的值由“喝水是生命体通过口腔摄入水分的方式,人体每天通过口腔摄入的液体大约有2升”改为“喝水增加了尿量,能使有害物质及时排出体内”

4.3 文档删除

4.3.1 删除单个文档

语法:db.COLLECTION_NAME.remove( <query>,{ justOne:<boolean>,writeConcern:<document>})

db.集合名.remove({条件})

eg:删除集合collection_137中键nickname为“爱德华”的文档

查看集合中所有文档,验证文档是否删除成功

4.3.2 删除全部文档

语法:db.COLLECTION_NAME.remove({})

【 db.集合名.remove({})

  • db:当前数据库对象。

  • COLLECTION_NAME:当前集合对象。

  • remove():删除文档方法。

  • quert:删除文档的条件,可选参数。

  • justOne:<boolean>的boolean为true或1时,表示只删除查询出的第一个文档。

  • writeConcern:<document>表示抛出异常级别。

eg:删除集合product中全部文

5. 文档简单查询

5.1 查询所有文档

语法:db.COLLECTION_NAME.find()

db.集合名.find()

  • 查询所有文档,以易读的方式展示

语法:db.COLLECTION_NAME.find().pretty()

db.集合名.find().pretty()

  • db:当前数据库对象。
  • COLLECTION_NAME:当前集合对象。

  • find():查询所有文档方法。

  • pretty():格式化查询返回结果。

eg:查看集合collection_137中所有文档

以易读方式查看集合collection_137中所有文档

5.2 按条件查询文档

5.2.1 与操作符 $and

语法:db.COLLECTION_NAME.find({$and:[{<key1>:<value1>,<key2>:<value2>}]}).pretty()

db.集合名.find({$and:[{"键1":"值1","键2","值2"}]}).pretty() 】

eg:使用“与”操作符,查询集合colletion_137中同时满足userid1005nickname为罗密欧的文档

5.2.2 或操作符($or)

语法:db.COLLECTION_NAME.find({$or:[{<key1>:<value1>},{<key2>:<value2>}]}).pretty()

db.集合名.find({$or:[{"键1","值1"},{"键2","值2"}]}).pretty() 】

eg:使用“或”操作符,查询集合colletion_137中userid1002userid1003的文档

5.2.3 大于操作符($gt)

语法:db.COLLECTION_NAME.find({<key>:{$gt:<value>}}).pretty()

db.集合名.find({"键":{$gt:"值"}}).pretty()

eg:使用“大于”操作符,查询集合colletion_137中userid大于1005的文档

5.2.4 小于操作符($lt)

语法:db.COLLECTION_NAME.find({<key>:{$lt:<value>}}).pretty()

db.集合名.find({"键":{$lt:"值"}}).pretty()

eg:使用“小于”操作符,查询集合colletion_137中userid小于1004的文档

5.2.5 大于等于操作符($gte)

语法:db.COLLECTION_NAME.find({<key>:{$gte:<value>}}).pretty()

db.集合名.find({"键":{$gte:"值"}}).pretty() 】

eg:使用“大于等于”操作符,查询集合colletion_137中userid大于等于1005的文档

5.2.6 小于等于操作符($lte)

语法:db.COLLECTION_NAME.find({<key>:{$lte:<value>}}).pretty()

【 db.集合名.find({"键":{$lte:"值"}}).pretty()

eg:使用“小于等于”操作符,查询集合colletion_137中userid小于等于1003的文档

5.2.7 不等于操作符($ne)

语法:db.COLLECTION_NAME.find({<key>:{$ne:<value>}}).pretty()

【 db.集合名.find({"键":{$ne:"值"}}).pretty()

eg:使用“不等于”操作符,查询集合colletion_137中userid不等于1005的文档

5.2.8 包含操作符($in)

语法:db.COLLECTION_NAME.find({<key>:{$in:[<key>:<value>]}}).pretty()

【 db.集合名.find({"键":{$in:["值1","值2"]}}).pretty()

eg:使用“包含”操作符,查询集合colletion_137中_id包含13的文档

5.2.9 不包含操作符($nin)

语法:db.COLLECTION_NAME.find({<key>:{$nin:[<key>:<value>]}}).pretty()

【 db.集合名.find({"键":{$nin:["值1","值2"]}}).pretty()

eg:使用“不包含”操作符,查询集合colletion_137中_id不包含135的文档

5.3 按特定类型查询文档

5.3.1 Null类型查询

【 用于查询集合中字段值为Null的文档 】

语法:db.COLLECTION_NAME.find({<key>:null}).pretty()

db.集合名.find({"键":null}).pretty()

eg:使用Null类型查询,查询集合colletion_137中字段statenull的文档

5.3.2 正则表达式查询

【 用于查询集合中符合某个规则的文档 】

语法:db.COLLECTION_NAME.find({<key>:/正则表达式/}).pretty()

db.集合名.find({"键":/正则表达式/}).pretty()

eg:使用正则表达式查询,查询集合colletion_137中评论内容content值以“专家”开头的文档

5.3.3 嵌套文档查询之精确查询

【用于集合中指定子文档,查询符合的文档】

语法:db.COLLECTION_NAME.find({<key>:{<key1>:<value1>,<key2>:<value2>}}).pretty()

【 db.集合名.find({"键":"值"}).pretty() 】

eg:使用精确查询,查询集合colletion_137中包含子文档homePhonemobilePhone且值分别为6277154113262984142的文档

5.3.4 嵌套文档查询之点查询

【 用于集合中指定子文档中一个字段,查询包含该字段的文档 】

语法:db.COLLECTION_NAME.find({<key>.<key1>:<value1>}).pretty()

【 db.集合名.find({"键1.键2"."值"}).pretty()

eg:使用点查询,查询集合colletion_137中包含子文档homephone且值为82174911的文档

6. 聚合操作

6.1 聚合管道操作

  聚合管道操作是将文档在一个管道处理完毕后,把处理的结果传递给下一个管道进行再次处理。聚合管道是使用不同的管道阶段操作器进行不同聚合操作,管道阶段操作器也可称为管道操作符,常见管道操作符如下:

6.1.1 $group操作符

语法:db.COLLECTION_NAME.aggregate([{$group:{<key1>:"$<key2>"}]).pretty()

db.集合名.aggregate([{$group:{"_id":"$键2"}}]).pretty()

  • _id:表示分组条件(必填),指定为null时以整个文档为一组。

eg:使用$group操作符,将集合colletion_137中的文档按userid进行分组

6.1.2 $limit操作符

语法:db.COLLECTION_NAME.aggregate({$limit:整型数字}).pretty()

db.集合名.aggregate({$limit:整型数字}).pretty()

eg:使用$limit操作符,展示集合colletion_137中前三个文档

6.1.3 $match操作符

语法:db.COLLECTION_NAME.aggregate([{$match:{<key>:<value>}}]).pretty()

db.集合名.aggregate([{$match:{"键":"值"}}]).pretty()

eg:使用$match操作符,将集合colletion_137中键nickname的值为罗密欧的文档查询出来

6.1.4 $sort操作符

语法:db.COLLECTION_NAME.aggregate([{$sort:{<key>:-1或1}}]).pretty()    

  • -1表示降序,1表示升序

db.集合名.aggregate([{$sort:{"键":-1或1}}]).pretty()

eg:使用$sort操作符,将集合colletion_137中的文档按照键age的值进行降序排序

6.1.5 $project操作符

语法:db.COLLECTION_NAME.aggregate([{$project:{<key>:<value>}}]).pretty()

db.collection_137.aggregate([{$project:{"键":"值"}}]).pretty() 】

eg:使用$project操作符,展示集合colletion_137中的文档,并且文档均不包含字段_id

6.1.6 $skip操作符

语法:db.COLLECTION_NAME.aggregate({$skip:整型数字}).pretty()

db.集合名.aggregate({$skip:整型数字}).pretty()

eg:使用$skip操作符,展示集合colletion_137中的_id56的文

  管道阶段操作器的值被称为管道表达式,并且每个管道表达式都是一个文档结构,由字段名称、字段值和管道表达式组成。常见的管道表达式如下:

6.1.7 $sum表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$sum:$<key3>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$sum:"$键3"}}}]).pretty()

eg:使用$sum表达式,将集合product中的文档按类型type进行分组并计算各个分组的价格price总和

6.1.8 $avg表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$avg:$<key3>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$avg:"$键3"}}}]).pretty() 】

eg:使用$avg表达式,将集合product中的文档按类型type进行分组,并计算各个分组的价格price平均值

6.1.9 $min表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$min:$<key3>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$min:"$键3"}}}]).pretty()

eg:使用$min表达式,将集合product中的文档按类型type进行分组,并计算各个分组中价格price最小值

6.1.10 $max表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$max:$<key3>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$max:"$键3"}}}]).pretty()

eg:使用$max表达式,将集合product中的文档按类型type进行分组,并计算各个分组中价格price最大值

6.1.11 $push表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$push:$<key3>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$push:"$键4"}}}]).pretty()

eg:使用$push表达式,将集合product中的文档按类型type进行分组,并将各个分组的产品插入到一个数组tags

6.1.12 $first表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$first:$<key4>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$first:"$键4"}}}]).pretty()

eg:使用$first表达式,将集合product中的文档按类型type进行分组,并获取各个分组中第一个产品

6.1.13 $last表达式

语法:db.COLLECTION_NAME.aggregate([{管道操作符:{<key1>:"$<key2>

,<key3>:{$last:$<key5>}}}]).pretty()

【 db.集合名.aggregate([{管道操作符:{"键1":"$键2","键3":{$last:"$键4"}}}]).pretty()

eg:使用$last表达式,将集合product中的文档按类型type进行分组,并获取各个分组中最后一个产品

6.2 Map-Reduce操作

  MongoDB提供Map-Reduce操作来进行聚合操作。通常,Map-Reduce操作有两个阶段,即MapReduce阶段,其中Map阶段是对集合中的每个输入文档进行处理,处理结束后输出一个或多个结果,Reduce阶段是将Map阶段输出的一个或多个结果进行合并输出。

6.2.1 操作流程

  1. query阶段,查询集合orders中字段statusA的文档

  2. map阶段,按照字段cust_id进行分组,将字段cust_id相同的amount值放到一个数组中

  3. reduce阶段,通过函数sum对每组的amount值进行求和

  4. output阶段,将结果输出到集合order_totals

6.2.2 语法

  • mapReduce():用于对当前集合进行聚合操作的函数。
  • map映射函数:map函数调用emit(key,value)方法,遍历集合中的所有文档,返回key-value键值对,并将keyvalue输入到reduce函数中。
  • reduce统计函数:reduce函数主要是将key-values变成key-value,即将values数组变成单一的值value
  • 参数query:主要用于筛选文档,满足条件的文档才会调用map函数。
  • 参数out:用于存放聚合统计后的结果。
  • 参数sort:一般结合limit参数进行使用,在满足条件的文档输入map函数之前进行排序操作。
  • 参数limit:用于限定输入map函数的文档数量。

eg:查询集合comment中字段state1的文档,按照字段nickname对文档进行分组,计算出每个评论者的评论条数。

7. 使用索引优化查询

7.1 索引概述

  MongoDB数据库提供了多样性的索引支持,因此可以提高查询集合中文档的效率。若是没有索引,MongoDB数据库必须执行全集合扫描(即扫描集合中的每一个文档),从而筛选出与查询条件相匹配的文档。这种扫描全集合的查询效率是非常低的,尤其是在处理海量数据时,执行查询操作需要花费几十秒甚至几分钟的时间,这无疑对网站的性能是非常致命的。若是执行查询操作时,集合中的文档存在适当的索引,MongoDB就可以使用该索引限制必须检查的文档数量。

  索引是一种特殊的数据结构,即采用B-Tree数据结构。索引是以易于遍历读取的形式存储着集合中文档的一小部分,文档的一小部分指文档中的特定字段或一/多组字段,并且这些字段均按照字段的值进行排序。索引项的排序支持有效的等值匹配和基于范围的查询操作。此外,MongoDB还可以使用索引中的排序返回排序的结果。

7.1.1 单字段索引

  MongoDB支持在文档的单个字段上创建用户定义的升序/降序索引,因此被称为单字段索引(Single Field Index)。默认情况下,MongoDB中所有集合在“_id”字段上都有一个索引,用户也可以根据自己的需求添加额外索引来支持重要的查询和操作。由于MongoDB可以从任何方向遍历索引,因此对于单个字段索引和排序操作来说,索引项的排序顺序(即升序或降序)并不重要。

  在集合collection中的字段score上创建了一个索引,并指定其为有序。

7.1.2 复合索引

  MongoDB除了支持单字段索引外,还支持复合索引。所谓复合索引,就是包含多个字段的索引,一个复合索引最多可以包含31个字段。需要注意的是,若某字段属于哈希索引,则这时复合索引就不能包括该字段。

  复合索引是由{userid:1score:-1}组成的,因此复合索引首先按字段userid进行升序排序,然后在每个字段userid的值内,按照score降序排序。

7.1.3 多键索引

  若文档中的字段为数组类型,则每个字段都是数组中的一个元素,MongoDB将会为数组中的每个元素创建索引,因此被称为多键索引(Multikey Index)。多键索引允许通过匹配数组的一个或多个元素来查询包含该数组的文档。如果索引字段包含数组值,则MongoDB会自动确定是否创建多键索引,而无需显式地指定创建多键索引。

  集合collection中文档字段addr是一个数组类型,数组值包含两个元素,分别是{zip: “10036”…}{zip:“94301”…}。因此,MongoDB会自动创建多键索引,即{“addr.zip”:1}

7.1.4 地理空间索引

  为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引,即返回结果时使用平面几何的二维索引(2d索引)和返回结果时使用球面几何的二维球面索引(2dsphere索引)。其中,2d索引支持在欧几里德平面上的计算,也支持计算球面上的距离;2dsphere索引支持球面上几何计算的查询,包含查询(在一个指定多边形内的位置进行查询)、 交集查询(查询指定几何相交的位置)和临近查询(如查询离另一个点最近的点)。我们可以通过将2d索引和2dsphere索引进行相结合,从而进行高效的地理空间查询。

7.1.5 文本索引

  MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容,即进行文本检索查询。文本索引不存储特定语言的停止词,例如“the”、“a”以及“or”等词,而是将集合中的词作为词干,只存储根词。为了执行文本检索查询,则集合上必须有一个text索引。一个集合只能拥有一个文本检索索引,但是这个索引可以覆盖多个字段。

7.1.6 哈希索引

  为了支持基于哈希分片键进行分片,MongoDB提供了哈希索引类型。哈希索引是使用哈希函数来计算索引字段的哈希值,若是该索引字段的哈希值在哈希索引的范围内,则分布的更加随机。需要注意的是,哈希索引只支持等值匹配,不支持基于范围的查询。

7.2 索引操作

7.2.1 查看索引

语法:db.COLLECTION_NAME.getIndexes()

db.集合名.getIndexes() 】

eg:查询数据库articledb_137中集合collection_137的索引

7.2.2 查看索引大小

语法:db.COLLECTION_NAME.totalIndexSize()

db.集合名.totalIndexSize()

eg:查询数据库articledb_137中集合collection_137的索引大小

7.2.3 创建索引

语法:db.COLLECTION_NAME.createIndex(keys,options)

db.集合名.createIndex()

  • keys:指定索引键及排序顺序,该参数值为文档类型

  • key用于指定索引键,value指定排序顺序,1为升序,-1为降序。

  • options:用于控制创建索引的选项,常见选项有uniquename,其中unique描述建立的索引是否唯一,默认为falsename描述所创建索引的名称,默认情况下MongoDB会通过连接索引的字段名和排序顺序生成一个索引名称。

eg:在集合collection_137的字段userid上创建单字段索引,并指定顺序为升序。

        在集合collection_137的字段userid和字段nickname上创建复合索引,指定字段userid 为升序,字段nickname为降序。

7.2.4 删除索引

删除单个索引

语法:db.COLLECTION_NAME.dropIndex(index)

  • 参数index,其数据类型为字符串或文档,可用于指定要删除的索引。

db.集合名.dropIndex(index)

eg:删除集合comment字段userid上的单字段索引。

删除所有索引

语法:db.COLLECTION_NAME.dropIndexes()

【 db.集合名.dropIndexes()

eg:删除所有索引。

8. 使用Python操作MongoDB

9. 安全与访问控制

9.1 用户访问控制

9.1.1 创建管理员用户

  启用用户访问控制之前,必须确保数据库admin中拥有userAdminuserAdminAnyDatabase角色的用户(即管理员用户)。

  1. 通过user_mongo用户启动MongoDB服务,登录mongo shell。 【mongo】
  2. 切换到数据库admin。 【use admin】
  3. 查看数据库admin中的用户列表,查看是否已经创建相关用户。 【show users】

  4. 创建管理员用户。 【db.createUser({user:"itcastAdmin",pwd:passwordPrompt(),roles:[{role:"userAdminAnyDatabase",db:"admin"}]})】   (执行时须在"Enter Passwork:"处输入设置的密码)。

9.1.2 开启用户访问控制

  MongoDB是使用基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对MongoDB服务的访问,即通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限。在MongoDB未对用户分配角色之前,用户是无法连接并访问MongoDB。我们可以在MongoDB服务启动时,添加参数“--auth”,开启用户访问控制,也可以在启动MongoDB服务的配置文件中,添加参数“authorization: enabled”,开启用户访问控制。

  • 在启动MongoDB服务的配置文件mongo.conf中,添加如下参数开启用户访问控制(添加之前需要关闭MongoDB服务)。

  • 配置文件修改完成后,重启MongoDB服务使配置生效。
  • 执行 mongo 命令进入 mongo shell
  • 执行 use admin 命令切换到数据库admin
  • 执行 db.auth("itcastAdmin",passwordPrompt()) 命令进行用户验证,输入密码,验证通过则返回1

 9.1.3 MongoDB数据库的内置角色及相关权限说明

9.2 用户管理操作

9.2.1 创建用户

eg:使用管理员用户itcastAdmin在数据库admin中创建一个基于角色read的用户itcastUser,并且该用户只具有admin数据库的read权限:

db.createUser({user:"itcastUser",pwd:passwordPrompt(),roles:[{role:"read",db:"admin"}]})

  需要注意得是在创建用户时,使用passwordPrompt()方法创建用户密码时,需在执行创建用户命令后在“Enter password:”提示时设置用户密码

9.2.2 查看用户信息

eg:使用管理员用户itcastAdmin查看普通用户itcastUser的信息:

db.getUser("itcastUser")

使用管理员用户itcastAdmin查看普通用户itcastUser的权限:

db.getUser("itcastUser",{showPrivileges:true})

 9.2.3 添加用户角色

使用管理员用户itcastAdmin为普通用户itcastUser添加readWrite角色:

db.grantRolesToUser("itcastUser",[{role:"readWrite",db:"admin"}])

 9.2.4 修改用户信息

使用管理员用户itcastAdmin将普通用户itcastUserreadWrite角色修改为readAnyDatabase:

db.updateUser("itcastUser",{roles:[{role:"read",db:"admin"},
{role:"readAnyDatabase",db:"admin"}]})

9.2.5 删除用户角色

使用管理员用户itcastAdmin删除普通用户itcastUser中的readAnyDatabase角色:

db.revokeRolesFromUser("itcastUser",[{role:"readAnyDatabase",db:"admin"}])

9.2.6 修改用户密码

使用管理员用户itcastAdmin修改普通用户itcastUser的密码,修改为itcastuser,并执行验证命令验证使用新密码是否可以通过验证:

db.changeUserPassword("itcastUser","itcastuser")

9.2.7 删除用户

使用管理员用户itcastAdmin删除普通用户itcastUser:

db.dropUser("itcastUser")

查看用户itcastUser是否删除成功:

show users

10.  部署副本集

10.1 环境准备

  通过三台虚拟机部署官方推荐方案的副本集,该副本集包含一个主节点和两个副本节点,三台虚拟机的创建可参考本书资源中提供的环境配置文档,副本集各服务器的基本信息及角色分配如下表:

  • 分别在三台服务器上创建user_mongo用户(如已创建则无需再执行)
adduser user_mongo
passwd user_mongo
  • 分别将目录/opt/servers/mongodb_demo/更改为用户user_mongo的权限(如已更改权限则无需再执行)
chown –R user_mongo:user_mongo /opt/servers/mongodb_demo/

  • 在三台服务器目录/opt/servers/mongodb_demo/下创建目录/replicaset/data/,用于存放副本集数据的目录。
mkdir -p /opt/servers/mongodb_demo/replicaset/data/
  • 在三台服务器目录/opt/servers/mongodb_demo/下创建目录/replicaset/logs/,用于存放副本集日志的目录。           

mkdir -p /opt/servers/mongodb_demo/replicaset/logs/
  • 在三台服务器的目录/opt/servers/mongodb_demo/replicaset/logs/下创建日志文件。

touch /opt/servers/mongodb_demo/replicaset/logs/mongodb.log

10.2 副本集的安装与启动

10.2.1 安装副本集

  • 打开Linux虚拟机并通过远程工具CRT连接Linux平台。

  • 切换到user_mongo用户。

su user_mongo
  • MongoDB安装包上传到服务器nosql01/opt/software/目录下。

cd /opt/software/
sudo rz
  • MongoDB安装包修改为用户user_mongo权限。

sudo chown user_mongo:user_mongo /opt/software/mongodb-linux-x86_64-rhel70-4.2.2.tgz
  • MongoDB安装包解压到目录/opt/servers/mongo_demo/replicaset/下。

tar -zxvf /opt/software/mongodb-linux-x86_64-rhel70-4.2.2.tgz -C /opt/servers/mongodb_demo/replicaset/
  • 重命名MongoDB文件夹名称。
mv mongodb-linux-x86_64-rhel70-4.2.2/ mongodb
  • 将服务器nosql01/opt/servers/mongodb_demo/replicaset/目录下的所有内容分发到服务器nosql02和服务器nosql03上,该目录下包含dataMongoDB数据存放目录)、logsMongoDB日志存放目录)和mongodbMongoDB安装目录)。
scp -r /opt/servers/mongodb_demo/replicaset/ user_mongo@nosql02:/opt/servers/mongodb_demo/
scp -r /opt/servers/mongodb_demo/replicaset/ user_mongo@nosql03:/opt/servers/mongodb_demo/

10.2.2 启动副本集

分别在三台服务器nosql01nosql02nosql03上启动MongoDB服务。

  • 进入/opt/servers/mongodb_demo/replicaset/mongodb/bin目录。
cd /opt/servers/mongodb_demo/replicaset/mongodb/bin
  • 以副本集模式启动MongoDB
./mongod --replSet itcast --dbpath=/opt/servers/mongodb_demo/replicaset/data/ --logpath=/opt/servers/mongodb_demo/replicaset/logs/mongodb.log --port 27017 --bind_ip nosql01 --logappend --fork

🔹参数replSet:副本集名称

🔹参数dbpath:数据存放目录

🔹参数logpath:日志存放目录

🔹参数logappend:追加方式写入日志

🔹参数fork:后台运行

10.3 副本集的初始化

登录服务器nosql01MongoDB客户端。

  • 进入MongoDBbin目录。

cd /opt/servers/mongodb_demo/replicaset/mongodb/bin
  • 登录MongoDB客户端。

./mongo --host nosql01 --port 27017

  • 在服务器nosql01MongoDB客户端中执行副本集初始化操作。

rs.initiate()

  若客户端返回信息中字段“OK”的值为1,则说明成功初始化副本集。

  完成初始化命令,当前节点默认处于“SECONDARY(副本节点)”状态,等待几秒后自动选举自己为“PRIMARY(主节点)”。

  • 将服务器nosql02中的MongoDB以副本节点的角色添加到副本集中。

rs.add("nosql02:27017")
  • 将服务器nosql03中的MongoDB以副本节点的角色添加到副本集中。

rs.add("nosql03:27017")

  若执行添加副本节点命令,客户端返回的信息中字段“OK”的值为1,则证明副本节点添加成功。

  • 在服务器nosql02nosql03中登录MongoDB客户端。

10.4 查看副本集成员状态

  在MongoDB副本集主节点的MongoDB客户端查看各成员状态信息。

  • 进入服务器nosql01MongoDBbin目录。

cd /opt/servers/mongodb_demo/replicaset/mongodb/bin
  • 登陆MongoDB客户端。
./mongo --host nosql01 --port 27017
  • 查看副本集成员状态信息。
rs.status()

10.5 同步副本文档

10.5.1 在副本集节点写入数据

  • 进入服务器nosql01(副本集主节点)中MongoDBbin目录。
cd /opt/servers/mongodb_demo/replicaset/mongodb/bin
  • 登陆MongoDB客户端。
./mongo --host nosql01 --port 27017
  • 切换到test数据库。
use test
  • 创建集合user并插入一条文档。
db.user.insert({"name":"bozai"})
  • 查看文档是否写入成功。
db.user.find()

10.5.2 在副本节点验证数据是否同步成功

  • 进入服务器nosql02(副本集副本节点)中MongoDBbin目录。

cd /opt/servers/mongodb_demo/replicaset/mongodb/bin
  • 登陆MongoDB客户端。

./mongo --host nosql02 --port 27017
  • 切换到test数据库。

use test
  • 查看文档是否写入成功。

db.user.find()  //由于副本节点默认没有读取副本集内容权限,因此会报错。

  • 开启副本节点读取权限。

rs.slaveOk()  //开启读取权限后再次执行查看文档命令

10.6 故障转移

  在服务器nosql01中关闭MongoDB服务,在此之前需要在MongoDB客户端中执行exit命令退出MongoDB客户端。

  • 查看MongoDB服务运行的进程。
ps -ef | grep mongod
  • 关闭MongoDB服务进程。
kill -2 进程号

  • 登陆服务器nosql02nosql03的客户端,验证这两个副本节点中是否实现自动故障转移,从两个副本节点中选出新的主节点。( MongoDBbin目录)。
./mongo --host nosql02 --port 27017

  发现服务器nosql02中MongoDB客户端变更为主节点。证明副本集的自动故障转移功能可以正常使用。

./mongo --host nosql03 --port 27017

10.7 配置副本集成员

10.7.1 获取副本集成员配置信息

  由于故障转移操作后,副本集主节点由服务器nosql01变为服务器nosql02,因此后续操作需要在服务器nosql02中进行

  • 进入服务器nosql02MongoDBbin目录
cd /opt/servers/mongodb_demo/replicaset/mongodb/bin
  • 登录MongoDB客户端。

./mongo --host nosql02 --port 27017
  • 将副本集成员信息赋值到变量cfg中。

cfg=rs.conf()

10.7.2 调整副本集成员的优先级

  在MongoDB副本集中除了仲裁节点外,其它每一个成员都存在优先级,能够手动设置优先级来决定哪个成员会被选举成为Primary(主节点)的权重最大。副本集中通过设置参数priority的值来决定优先级的大小,该值的范围是0-100,值越大则优先级越高,当值为0时,该节点便不能成为Primary。在资源不均衡的副本集环境中,可以指定资源较差的服务器中的成员不能成为Primary

  • 将“_id”0的副本节点(即服务器nosql01)优先级值由1改为2
cfg.members[0].priority = 2

  上述命令中,members[0]中的0与副本集配置信息中的字段_id的值没有直接关系,因为_id的值是可以修改的,这里的0指该副本节点在副本集配置信息中的字段members中数组位置。

  • 将调整副本集成员优先级的操作应用到副本集。
rs.reconfig(cfg)

  在客户端返回的信息中可以看到字段OK的值为1,证明成功将副本节点(服务器nosql01)的优先级调整为2,此时在服务器nosql01中登录MongoDB客户端会发现当前副本集角色变为主节点(PRIMARY)。

10.7.3 配置隐藏节点

  隐藏节点是副本节点的一种表现形式,它不能被客户端引用,也就是说这个节点不能用于读写分离的场景。不过对于其它副本节点和主节点来说都是可见的,因此隐藏副本节点依然可以投票,依然可以同步主节点的数据副本,只不过客户端无法读取隐藏副本节点的数据,无法实现负载功能。

  • 在服务器nosql01MongoDBbin目录下登录MongoDB客户端。
./mongo –-host nosql01 –-port 27017
  • 将副本集配置信息赋值到变量cfg
cfg = rs.conf()
  • 设置服务器nosql02中副本节点的优先级为0

cfg.members[1].priority = 0
  • 设置服务器nosql02中副本节点为隐藏节点。

cfg.members[1].hidden = true
  • 将调整副本集成员的操作应用到副本集。

rs.reconfig(cfg)

10.7.4 配置延迟节点

  延迟节点是副本节点的另一种表现形式,它代表此节点的数据与主节点的数据有一定的延迟同步,通过设定一个延迟的属性来确定。实现延迟副本节点的前提是该节点为隐藏节点。由于延迟副本节点会延迟复制主节点的数据集,因此可以从人为的误操作中恢复数据。

  • 将副本集配置信息赋值到变量cfg
cfg = rs.conf()
  • 设置服务器nosql03中副本节点的优先级为0

cfg.members[2].priority = 0
  • 设置服务器nosql03中副本节点为隐藏节点。

cfg.members[2].hidden = true

设置延迟时间为3600秒。

cg.members[2].slaveDelay = 3600
  • 将调整副本集成员的操作应用到副本集。

rs.reconfig(cfg)

10.7.5 配置副本集成员投票权

  副本集中允许有七个拥有投票权的成员,配置副本集成员拥有投票权需要修改参数votes的值为1,如修改值为0则代表该成员不具备投票权,默认情况下在副本集中创建的成员都具备投票权,即votes的值为1

  • 在服务器nosql01MongoDBbin目录下登录MongoDB客户端。

./mongo –-host nosql01 --port 27017
  • 将副本集配置信息赋值到变量cfg

cfg = rs.conf()
  • 设置服务器nosql02中隐藏节点的投票权设置为0,即不可投票。

cfg.members[1].votes = 0
  • 将调整副本集成员的操作应用到副本集。

rs.reconfig(cfg)

10.7.6 将副本节点转为仲裁节点

  • 在服务器nosql01MongoDBbin目录下登录MongoDB客户端。

./mongo –-host nosql01 –-port 27017
  • 将副本集配置信息赋值到变量cfg

cfg = rs.conf()
  • 移除服务器nosql02中的隐藏节点。

rs.remove("nosql02:27017")

  • 在服务器nosql02上退出MongoDB客户端并关闭MongoDB进程,备份MongoDB数据存放目录。

mv /opt/servers/mongodb_demo/replicaset/data /opt/servers/mongodb_demo/replicaset/data-old

  • 在服务器nosql02上创建一个新的MongoDB数据存放目录,并以该目录为数据存放目录在MongoDBbin目录下重新启动MongoDB
mkdir /opt/servers/mongodb_demo/replicaset/data-new

./mongod --replSet itcast --dbpath=/opt/servers/mongodb_demo/replicaset/data-new --logpath=/opt/servers/mongodb_demo/replicaset/logs/mongodb.log --port 27017 --bind_ip nosql02 --logappend --fork

  • 在副本集主节点(服务器nosql01)将该服务器nosql02中的MongoDB以仲裁节点的角色添加到副本集中
rs.addArb("nosql02:27017")

 10.8 安全认证

  默认情况下部署的MongoDB副本集不会开启安全认证功能,这样会对副本集的安全带来一定影响,任何人都可以操作副本集,这在生产环境中是不允许发生的。MongoDB 副本集之间通信有两种安全认证机制,一种是通过KeyFile,另外一种是通过证书x.509,官网推荐使用证书的方式,不过我们这里搭建测试和开发环境没必要去弄证书,因此我们直接通过配置KeyFile就可以实现安全通信,不过在生产环境中推荐使用证书x.509

  KeyFileMongoDB副本集安全认证的一种形式,该形式是通过一个密钥文件使副本集中各服务器进行内部通信使用,当作副本集内部的密码,这个密钥文件基本上是一个明文的文件,副本集中每个成员的密钥文件内容须保持一致。

密钥文件的使用需要注意以下几点:

  1. 内容至少包含六个字符,文件的大小不能超过1024字节
  2. 文件中的空白字符在认证过程没有实际意义
  3. 文件编码为base64,但不能包含等于号
  4. 密钥文件权限一定要等于或小于 600rw只有拥有者有读写权限),否则会报权限太高的错误

  MongoDB副本集中的KeyFile安全认证可以理解为MongoDB单机模式下的auth认证功能,开启KeyFile安全认证,就不需要再使用auth认证(隐含就是开启了auth),这个时候登录MongoDB副本集的客户端就需要用户名和密码进行认证。KeyFile认证不是必选项,不过副本集中一个成员开启了KeyFile认证的情况下,其它成员也必须开启KeyFile认证,否则将不会加入该副本集。 

 10.8.1 在MongoDB副本集中开启KeyFile安全认证功能

  • 创建用于存放KeyFile文件的目录。

mkdir -p /opt/servers/mongodb_demo/replicaset/key
  • /opt/servers/mongodb_demo/replicaset/key目录下新建KeyFile文件并命名为keyfile。

touch /opt/servers/mongodb_demo/replicaset/key/keyfile
  • 通过Linux系统提供的密码工具集 openssl生成符合KeyFile文件标准的密钥并写入。
openssl rand -base64 756 -out /opt/servers/mongodb_demo/replicaset/key/keyfile
  • 查看密钥是否成功写入KeyFile文件。

vi /opt/servers/mongodb_demo/replicaset/key/keyfile
  • 修改 nosql01,nosql02,nosql03 KeyFile文件权限为600,即只有当前用户拥有可读写权限。如不操作此步后续会因为KeyFile文件默认权限过大,无法启动安全认证的MongDB副本集。
chmod 600 /opt/servers/mongodb_demo/replicaset/key/keyfile
  • 为了保证副本集中各节点的KeyFile文件保持一致,需要将KeyFile文件(keyfile)拷贝到其它节点。
scp -r /opt/servers/mongodb_demo/replicaset/key user_mongo137@nosql02:/opt/servers/mongodb_demo/replicaset/
scp -r /opt/servers/mongodb_demo/replicaset/key user_mongo137@nosql03:/opt/servers/mongodb_demo/replicaset/
  • 开启安全认证后在不指定用户登录MongoDB客户端时,默认情况下我们是以访客身份登录没有任何操作的权限,也无法创建用户,这会导致开启了安全认证的副本集无法正常使用。因此,需要在没有开启安全认证的MongoDB副本集中添加全局管理用户。
//切换到admin数据库
use admin 

//创建全局管理用户itcastAdmin
db.createUser({user:"itcastAdmin",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"},{role:"readWriteAnyDatabase",db:"admin"},{role:"dbAdminAnyDatabase",db:"admin"}]})
  • 验证用户是否创建成功。
db.auth("itcastAdmin","123456")

  •  关闭副本集,即三台服务器的MongoDB服务(先副后主)。重新以安全认证模式启动副本集。
  • 在服务器nosql01MongoDBbin目录下启动MongoDB服务。
./mongod --replSet itcast --keyFile /opt/servers/mongodb_demo/replicaset/key/keyfile --dbpath=/opt/servers/mongodb_demo/replicaset/data/ --logpath=/opt/servers/mongodb_demo/replicaset/logs/mongodb.log --port 27017 --bind_ip nosql01 --logappend --fork
  • 在服务器nosql02MongoDBbin目录下启动MongoDB服务。
./mongod --replSet itcast --keyFile /opt/servers/mongodb_demo/replicaset/key/keyfile --dbpath=/opt/servers/mongodb_demo/replicaset/data-new --logpath=/opt/servers/mongodb_demo/replicaset/logs/mongodb.log --port 27017 --bind_ip nosql02 --logappend --fork
  • 在服务器nosql03MongoDBbin目录下启动MongoDB服务。
./mongod --replSet itcast --keyFile /opt/servers/mongodb_demo/replicaset/key/keyfile --dbpath=/opt/servers/mongodb_demo/replicaset/data/ --logpath=/opt/servers/mongodb_demo/replicaset/logs/mongodb.log --port 27017 --bind_ip nosql03 --logappend --fork

 10.8.2 验证安全认证是否成功启动

  • 在服务器nosql01MongoDBbin目录下不指定用户登录MongoDB客户端。
./mongo --host nosql01 --port 27017
  • 切换到数据库test。
use test
  • 查看集合user中的文档。
db.user.find()
  • 向集合user中插入文档。
db.user.insert({"name":"heima"})

  在执行读取和写入操作时会出现类似“command xxx requires authentication(执行xxx命令需要身份认证)”的错误信息。

  •  切换到admin数据库。
use admin
  • 通过全局管理用户itcastAdmin进行身份验证
db.auth("itcastAdmin","123456")
  • 切换到test数据库。
use test
  • 查看集合user中的文档。
db.user.find()
  • 向集合user中插入文档。
db.user.insert({"name":"heima"})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值