学习MongoDB4这一篇就够了


配套资料,免费下载
链接:https://pan.baidu.com/s/1xgEZUFvCpZXLrIZsX5mNjA
提取码:xqpn
复制这段内容后打开百度网盘手机App,操作更方便哦

第一章 MongoDB概述

1.1、MongoDB概述

MongoDB是由C++语言编写的基于分布式文件存储的开源数据库系统,旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。它支持的数据结构非常松散,是类似json的bson格式,因此可以存储比较复杂的数据类型。MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

1.2、MongoDB特点

  1. 高性能:MongoDB提供高性能的数据持久性,特别是对嵌入式数据模型的支持减少了数据库系统上的I/O活动。
  2. 高可用性:MongoDB的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余。
  3. 高扩展性:MongoDB提供了水平可扩展性作为其核心功能的一部分。
  4. 查询丰富:MongoDB支持丰富的查询语言,支持读和写操作(CRUD),比如数据聚合、文本搜索和地理空间查询等。
  5. 其他特点:如无模式(动态模式)、灵活的文档模型等。

1.3、MongoDB体系结构

MySQL与MongoDB体系结构对比:

image-20200820111406172

SQL与MongoDB术语/概念对比:

SQL术语/概念MongoDB术语/概念SQL解释/MongoDB解释
databasedatabase数据库/数据库
tablecollection数据库表/集合
rowdocument数据记录行/文档
columnfield数据字段/域
indexindex索引/索引
table joins表连接/MongoDB不支持表连接查询
primary keyprimary key主键/MongoDB自动将_id字段设置为主键

1.4、MongoDB数据模型

MongoDB的小存储单位就是文档(document)对象,数据在MongoDB中以BSON(Binary-JSON)文档的格式存储在磁盘上。

BSON(Binary Serialized Document Format)是一种类JSON的一种二进制形式的存储格式,简称Binary JSON。BSON和JSON一样,支持内嵌的文档对象和数组对象,但是BSON有JSON没有的一些数据类型,如Date和BinData类型。BSON采用了类似于C语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具有轻量性、可遍历性、高效性的三个特点,可以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高,但它的缺点是空间利用率不是很理想。
BSON中,除了基本的JSON类型:string,integer,boolean,double,null,array和object,它还使用了特殊的数据类型,包括 date,object id,binary data,regular expression和code。

数据类型描述
String字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean布尔值。用于存储布尔值(真/假)。
Double双精度浮点值。用于存储浮点值。
Min/Max keys将一个值与 BSON元素的最低值和最高值相对比。
Array用于将数组或列表或多个值存储为一个键。
Timestamp时间戳。记录文档修改或添加的具体时间。
Object用于内嵌文档。
Null用于创建空值。
Symbol符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID对象 ID。用于创建文档的 ID。
Binary Data二进制数据。用于存储二进制数据。
Code代码类型。用于在文档中存储 JavaScript 代码。
Regular expression正则表达式类型。用于存储正则表达式。

第二章 MongoDB单机部署

官方网址:mongodb community ,由于网络下载较慢,我已经将所需要的资源打包放到了配套资料中。

2.1、Windows下单机部署

第一步:解压资源

image-20200820114103636

第二步:创建目录

需要创建一个data目录,在data目录中在创建一个db目录,db目录用于存放数据库数据

image-20200820114241045

在创建一个log目录用于存放MongoDB的日志文件

image-20200820114542768

在创建一个config目录用于存放MongoDB的启动配置信息

image-20200820114634663

在config目录中创建一个文本文件,名字叫mongod.conf,把以下配置信息复制进去即可

systemLog:
   destination: file
   #这里修改成你自己日志log目录地址,这里只能使用/千万不要用\
   path: "C:/DevTools/mongodb-win32-x86_64-2008plus-ssl-4.0.12/log/mongod.log"
   logAppend: true
net:
   port: 27017
   bindIp: "127.0.0.1"
storage:
   #这里修改成你自己数据库db地址,这里只能使用/千万不要用\
   dbPath: "C:/DevTools/mongodb-win32-x86_64-2008plus-ssl-4.0.12/data/db"
   journal:
      enabled: true

第三步:启动服务

进入bin目录,在地址栏输入cmd,然后回车,输入以下命令启动MongoDB服务端,mongod --config …/config/mongod.conf

image-20200820120504078

第四步:命令行连接

进入bin目录,在地址栏输入cmd,然后回车,输入以下命令启动MongoDB客户端,mongo --host=127.0.0.1 --port=27017

image-20200820120729555

第五步:图形化连接

直接解压mongodb-compass-community-1.16.4-win32-x64.zip,打开MongoDBCompassCommunity.exe

image-20200820124848044

image-20200820124913074

image-20200820174604494

image-20200820174629090

2.2、Linux下单机部署

第一步:解压资源

[root@caochenlei ~]# tar -zxvf mongodb-linux-x86_64-4.0.10.tgz
[root@caochenlei ~]# mv mongodb-linux-x86_64-4.0.10 mongodb
[root@caochenlei ~]# mv mongodb /usr/local/

第二步:创建目录

[root@caochenlei ~]# mkdir -p /usr/local/mongodb/data/db
[root@caochenlei ~]# mkdir -p /usr/local/mongodb/log
[root@caochenlei ~]# mkdir -p /usr/local/mongodb/config

第三步:编辑配置

[root@caochenlei ~]# vi /usr/local/mongodb/config/mongod.conf
systemLog:
   destination: file
   #这里修改成你自己日志log目录地址,这里只能使用/千万不要用\
   path: "/usr/local/mongodb/log/mongod.log"
   logAppend: true
net:
   #默认的端口
   port: 27017
   #虚拟机地址
   bindIp: "192.168.206.128"
storage:
   #这里修改成你自己数据库db地址,这里只能使用/千万不要用\
   dbPath: "/usr/local/mongodb/data/db"
   journal:
      enabled: true
processManagement:
   #是否使用后台模式启动
   fork: true

第四步:启动服务

[root@caochenlei ~]# /usr/local/mongodb/bin/mongod --config /usr/local/mongodb/config/mongod.conf
about to fork child process, waiting until server is ready for connections.
forked process: 27369
child process started successfully, parent exiting

第五步:命令行连接

[root@caochenlei ~]# /usr/local/mongodb/bin/mongo --host=192.168.206.128 --port=27017

第六步:关闭防火墙

[root@caochenlei ~]# service iptables stop
[root@caochenlei ~]# chkconfig iptables off

第六步:图形化连接

image-20200820221447046

image-20200820221508489

第三章 MongoDB基本语法

3.1、创建数据库

如果数据库不存在,则创建数据库,否则切换到指定数据库。

use 数据库名称

注意:在 MongoDB 中默认的数据库为 test,如果你没有创建新的数据库,集合将存放在 test 数据库中。

3.2、查看数据库

查看当前数据库:

db

查看所有数据库:

show dbs

注意: 在 MongoDB 中,数据库只有在内容插入后才会创建!

系统保留数据库:

  • admin:从权限的角度来看,这是"root"数据库,要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限,一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
  • local:这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合 。
  • config:当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。

3.3、删除数据库

db.dropDatabase()

注意:主要用来删除已经持久化的数据库。

3.4、创建集合

语法格式:

db.createCollection(name, options)

参数说明:

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

命名规范:

  • 集合名不能是空字符串""。
  • 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
  • 集合名不能以"system."开头,这是为系统集合保留的前缀。
  • 集合名不能含有保留字符$。

可选参数:

字段类型描述
capped布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。
当该值为 true 时,必须指定 size 参数。
size数值(可选)为固定集合指定一个最大值,即字节数。 如果 capped 为 true,也需要指定该字段。
max数值(可选)指定固定集合中包含文档的最大数量。

注意:在插入文档时,MongoDB 首先检查固定集合的 size 字段,然后检查 max 字段。

演示案例:

> use articledb
switched to db articledb
> db.createCollection("article")
{ "ok" : 1 }
> show collections
article
>

3.5、查看集合

语法格式:

方式一:

show collections

方式二:

show tables

3.6、删除集合

db.集合名.drop()

3.7、插入文档

语法格式:

方式一:

db.集合名.insert(document)

方式二:

db.集合名.insertOne(
   <document>,
   {
      writeConcern: <document>
   }
)

方式三:

db.集合名.insertMany(
   [ <document 1> , <document 2>, ... ],
   {
      writeConcern: <document>,
      ordered: <boolean>
   }
)

参数说明:

  • document:要写入的文档。
  • writeConcern:写入策略,默认为 1,即要求确认写操作,0 是不要求。
  • ordered:指定是否按顺序写入,默认 true,按顺序写入。

演示案例:

方式一:

db.comment.insert({"articleid":"100086","content":"床前明月光,疑是地上霜!","userid":"1006","nickname":"李晓晓","createdatetime":new Date("2019-0805T22:08:15.522Z"),"likenum":NumberInt(500),"state":"0"})

方式二:

db.comment.insertOne({"articleid":"100006","content":"相信自己,一定可以!","userid":"1002","nickname":"张三丰","createdatetime":new Date("2019-0805T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"})

方式三:

db.comment.insertMany([{"_id":"1","articleid":"100001","content":"健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"张三","createdatetime":new Date("2019-0805T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"}, {"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"李四","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"}, {"_id":"3","articleid":"100002","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"王五","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"}, {"_id":"4","articleid":"100003","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"张良","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"}])

3.8、查询文档

语法格式:

db.集合名.find(query, projection)[.pretty()]

参数说明:

  • query:可选,使用查询操作符指定查询条件。
  • projection:可选,使用投影操作符指定返回的键,查询时返回文档中所有键值,只需省略该参数即可(默认省略)。
  • .pretty():可选,是否格式化文档,这是一个函数并不是参数,放在这里只是想让大家知道格式化文档使用这个。

查询所有:

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

条件查询:

操作格式范例MySQL中的类似语句
等于{<key>:<value>}db.集合名.find({"name":"张三"}).pretty()where name = '张三'
小于{<key>:{$lt:<value>}}db.集合名.find({"age":{$lt:50}}).pretty()where age < 50
小于或等于{<key>:{$lte:<value>}}db.集合名.find({"age":{$lte:50}}).pretty()where age <= 50
大于{<key>:{$gt:<value>}}db.集合名.find({"age":{$gt:50}}).pretty()where age > 50
大于或等于{<key>:{$gte:<value>}}db.集合名.find({"age":{$gte:50}}).pretty()where age >= 50
不等于{<key>:{$ne:<value>}}db.集合名.find({"age":{$ne:50}}).pretty()where age != 50

连接查询:

AND连接:

db.集合名.find({key1:value1, key2:value2}).pretty()

注意:以上实例中类似于 WHERE 语句:WHERE key1=value1 AND key2=value2

OR连接:

db.集合名.find({$or: [{key1: value1}, {key2:value2}]}).pretty()

注意:以上实例中类似于 WHERE 语句:WHERE key1=value1 OR key2=value2

AND 和 OR 一块连接:

db.集合名.find({key1:value1,$or: [{key2:value2}, {key3:value3}]}).pretty()

注意:以上实例中类似于 WHERE 语句:WHERE key1=value1 AND ( key2=value2 OR key3=value3 )

类型查询:

$type操作符是基于BSON类型来检索集合中匹配的数据类型并返回结果,MongoDB 中可以使用的类型如下表所示:

类型数字备注
Double1
String2
Object3
Array4
Binary data5
Undefined6已废弃。
Object id7
Boolean8
Date9
Null10
Regular Expression11
JavaScript13
Symbol14
JavaScript (with scope)15
32-bit integer16
Timestamp17
64-bit integer18
Min key255Query with -1.
Max key127

如果想获取comment集合中nickname为String的数据,您可以使用以下命令:

db.comment.find({"nickname":{$type:2}})
或
db.comment.find({"nickname":{$type:"string"}})

分页查询:

  • .skip(NUMBER):跳过指定数量的数据记录。
  • .limit(NUMBER):读取指定数量的数据记录。
db.集合名.find().skip(跳过几条).limit(读取几条)

投影查询:

有时候,我们并不想让一条文档的信息全部显示出来,只想显示其中的一个或者几个字段,我们可以使用数字标识,1:显示、0:不显示,比如,我想要显示前边comment集合中的所有nickname,您可以使用以下命令:

db.comment.find({},{"nickname":1,"_id":0})

注意:_id默认会显示,我们不想看见就让它为0,第一个{}可以放查询条件

排序查询:

在 MongoDB 中使用 sort() 方法对数据进行排序,sort() 方法可以通过参数指定排序的字段,并使用1和-1来指定排序的方式,其中1为升序排列,而-1是用于降序排列。如果您想要让comment集合中的userid降序、likenum升序,您可以使用以下命令:

db.comment.find({},{"userid":1,"likenum":1}).sort({"userid":-1,"likenum":1})

注意:skip(), limilt(), sort()三个放在一起执行的时候,执行的顺序先是sort(),然后是skip(),最后是limit(),和命令编写顺序无关。

统计查询:

(1)、统计comment集合的所有的记录数:

db.comment.count()

(2)、统计comment集合中userid为1003的记录数:

db.comment.count({"userid":"1003"})

包含查询:

(1)、包含使用$in操作符,查询评论的集合中userid字段包含1003或1004的文档:

db.comment.find({"userid":{$in:["1003","1004"]}})

(2)、不包含使用$nin操作符,查询评论集合中userid字段不包含1003和1004的文档:

db.comment.find({"userid":{$nin:["1003","1004"]}})

正则查询:

MongoDB的模糊查询是通过正则表达式的方式实现的,正则表达式是js直接量的写法,格式为:

db.集合.find({字段:/正则表达式/})

如果要查询评论的内容中以“专家”开头的,代码如下:

db.comment.find({"content":/^专家/})

3.9、更新文档

语法格式:

db.集合名.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

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

演示案例:

db.comment.update({"articleid":"100086"},{$set:{"articleid":"10086"}})

注意:如果我们只想修改文档的某个字段请使用$set操作符修改,否则其它字段都会不见了

3.10、删除文档

语法格式:

db.集合名.remove(
   <query>,
   {
     justOne: <boolean>,
     writeConcern: <document>
   }
)

参数说明:

  • query:(可选)删除的文档的条件。
  • justOne:(可选)如果设为 true 或 1,则只删除一个文档,如果不设置该参数或使用默认值 false,则删除所有匹配条件的文档。
  • writeConcern:(可选)抛出异常的级别。

案例演示:

db.comment.remove({"articleid":"10086"})

注意:如果你想删除所有数据,可以使用以下方式:db.集合名.remove({})

第四章 MongoDB索引

4.1、创建索引

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

语法格式:

db.集合名.createIndex(keys, options)

参数说明:

参数类型描述
backgroundBoolean建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 “background” 默认值为false
uniqueBoolean建立的索引是否唯一。指定为true创建唯一索引。默认值为false
namestring索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
sparseBoolean对文档中不存在的字段数据不启用索引,这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false
expireAfterSecondsinteger指定一个以秒为单位的数值,完成 TTL设定,设定集合的生存时间。
vindex version索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weightsdocument索引权重值,数值在1到99999之间,表示该索引相对于其他索引字段的得分权重。
default_languagestring对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语。
language_overridestring对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language。

案例演示:

(1)、单字段索引

db.comment.createIndex({"articleid":1})

(2)、多字段索引

db.comment.createIndex({"articleid":1,"likenum":-1})

(3)、其它的索引

  • 地理空间索引(Geospatial Index):为了支持对地理空间坐标数据的有效查询,MongoDB提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面 几何的二维球面索引。

  • 文本索引(Text Indexes) :MongoDB提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如“the”、“a”、“or”), 而将集合中的词作为词干,只存储根词。

  • 哈希索引(Hashed Indexes):为了支持基于散列的分片,MongoDB提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支 持相等匹配,不支持基于范围的查询。

注意:其它的索引了解即可,不做重点!

4.2、查看索引

db.集合名.getIndexes()

4.3、删除索引

一、指定索引的移除

语法格式:

db.集合名.dropIndex(index)

案例演示:

db.comment.dropIndex({"articleid":1})

二、所有索引的移除

语法格式:

db.集合名.dropIndexes()

案例演示:

db.comment.dropIndexes()

注意: _id 的字段的索引是无法删除的,只能删除非 _id 字段的索引。

第五章 MongoDB聚合

5.1、聚合表达式

MongoDB中聚合(aggregate)主要用于处理数据(求平均值、求和等)并返回计算后的数据结果,有点类似sql语句中的 count(*)。

表达式描述实例
$sum计算总和。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", num_sum : { s u m : " sum : " sum:"likenum"}}}])
$avg计算平均值。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", num_avg : { a v g : " avg : " avg:"likenum"}}}])
$min获取集合中所有文档对应值的最小值。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", num_min : { m i n : " min : " min:"likenum"}}}])
$max获取集合中所有文档对应值的最大值。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", num_max : { m a x : " max : " max:"likenum"}}}])
$push在结果文档中插入值到一个数组中。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", articleid : { p u s h : " push: " push:"articleid"}}}])
$addToSet在结果文档中插入值到一个数组中。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", articleid : { a d d T o S e t : " addToSet : " addToSet:"articleid"}}}])
$first根据资源文档的排序获取第一个文档数据。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", first_articleid : { f i r s t : " first : " first:"articleid"}}}])
$last根据资源文档的排序获取最后一个文档数据。db.comment.aggregate([{KaTeX parse error: Expected '}', got 'EOF' at end of input: …roup : {_id : "userid", last_articleid : { l a s t : " last : " last:"articleid"}}}])

5.2、聚合管道

管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的参数。MongoDB的聚合管道将MongoDB文档在一个管道处理完毕后将结果传递给下一个管道处理,管道操作是可以重复的。这里我们介绍一下聚合框架中常用的几个操作:

操作符:

  • $project:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
  • $match:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
  • $limit:用来限制MongoDB聚合管道返回的文档数。
  • $skip:在聚合管道中跳过指定数量的文档,并返回余下的文档。
  • $unwind:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
  • $group:将集合中的文档分组,可用于统计结果。
  • $sort:将输入文档排序后输出。

案例演示:

(1)、$project演示:只显示userid、nickname这两个字段

db.comment.aggregate({$project:{_id:0,"userid":1,"nickname":1}})

(2)、$match演示:显示likenum大于700并且小于1500的文章信息

db.comment.aggregate({$match:{"likenum":{$gt:700,$lt:1500}}})

(3)、$limit演示:获取前两条数据

db.comment.aggregate({$limit:2})

(4)、$skip演示:跳过前两条数据

db.comment.aggregate({$skip:2})

(5)、$unwind演示:一个用户表user,其中一个字段是一个数组对象,存的是用户的奖励信息,这时需要统计用户10086所有奖励类型为B的总额。

#写入一条数据

db.user.insert(
{
    "user_id":10086,
    "bonus":[
        { type:"A",amount:1000 },
        { type:"B",amount:2000 },
        { type:"B",amount:3000 }
    ]
}
);
#拆分指定数组

db.user.aggregate({$unwind:"$bonus"});
#统计用户10086所有奖励类型为B的总额

db.user.aggregate([
{$match:{"user_id":10086}},
{$unwind:"$bonus"},
{$match:{"bonus.type":"B"}},
{$group:{_id:"$user_id",amount:{$sum:"$bonus.amount"}}}
]);

(6)、$group演示:按用户分组并查询每个用户的likenum总数

db.comment.aggregate([{$group:{_id:"$userid",num_sum:{$sum:"$likenum"}}}])

(7)、$sort演示:将文章的likenum以降序的形式输出

db.comment.aggregate({$sort:{"likenum":-1}})

第六章 MongoDB用户管理

6.1、概述

默认情况下,MongoDB实例启动运行时是没有启用用户访问权限控制的,也就是说,在实例本机服务 器上都可以随意连接到实例进行各种操作,MongoDB不会对连接客户端进行用户验证,这是非常危险的。为了强制开启用户访问控制(用户验证),则需要在MongoDB实例启动时使用选项–auth 或在指定启动配置文件中添加选项 auth=true。在开始之前需要了解一下概念:

  • 访问控制:MongoDB使用的是基于角色的访问控制(Role-Based Access Control,RBAC)来管理用户对实例的访问。通过对用户授予一个或多个角色来控制用户访问数据库资源的权限和数据库操作的权限,在对用户分配角色之前,用户无法访问实例。
  • 角色:在MongoDB中通过角色对用户授予相应数据库资源的操作权限,每个角色当中的权限可以显式指定, 也可以通过继承其它角色的权限,或者两都都存在的权限。
  • 权限:权限由指定的数据库资源(resource)以及允许在指定资源上进行的操作(action)组成。
    • 资源(resource)包括:数据库、集合、部分集合和集群。
    • 操作(action)包括:对资源进行的增、删、改、查操作。

6.2、相关命令

(1)、查询所有角色权限(仅用户自定义角色)

db.runCommand({ rolesInfo: 1 })

(2)、查询所有角色权限(包含内置角色)

db.runCommand({ rolesInfo: 1, showBuiltinRoles: true })

(3)、查询当前数据库中的某角色的权限

db.runCommand({ rolesInfo: "<rolename>" })

(4)、查询其它数据库中指定的角色权限

db.runCommand({ rolesInfo: { role: "<rolename>", db: "<database>" } }

(5)、角色授权

use 数据库名
db.grantRolesToUser("账户", [{role:"角色",db:"数据库名"}]) 

(6)、授权取消

use 数据库名
db.revokeRolesFromUser("账户",[{role:"角色",db:"数据库名"}])

6.3、内置角色

  • 数据库用户角色:read、readWrite
  • 所有数据库用户角色:readAnyDatabase、readWriteAnyDatabase、 userAdminAnyDatabase、dbAdminAnyDatabase
  • 数据库管理角色:dbAdmin、dbOwner、userAdmin
  • 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager
  • 备份恢复角色:backup、restore
  • 超级用户角色:root
  • 内部角色:system

6.4、具体角色

角色描述
read可以读取指定数据库中任何数据。
readWrite可以读写指定数据库中任何数据,包括创建、重命名、删除集合。
readAnyDatabase可以读取所有数据库中任何数据(除了数据库config和local之外)。
readWriteAnyDatabase可以读写所有数据库中任何数据(除了数据库config和local之外)。
userAdminAnyDatabase可以在指定数据库创建和修改用户(除了数据库config和local之外)。
dbAdminAnyDatabase可以读取任何数据库以及对数据库进行清理、修改、压缩、获取统 计信息、执行检查等操作(除了数据库config和local之外)。
dbAdmin可以读取指定数据库以及对数据库进行清理、修改、压缩、获取统计信息、执行检查等操作。
userAdmin可以在指定数据库创建和修改用户。
clusterAdmin可以对整个集群或数据库系统进行管理操作。
backup备份MongoDB数据最小的权限。
restore从备份文件中还原恢复MongoDB数据(除了system.profile集合)的权限。
root超级账号,超级权限

6.5、单实例配置

第一步:

使用之前Windows下部署好的MongoDB,启动mongod服务

第二步:

创建两个管理员用户,一个是系统的超级管理员myroot,一个是admin库的管理员myadmin

//切换到admin
use admin

//创建myroot
db.createUser({user:"myroot",pwd:"123456",roles:["root"]})

//创建myadmin
db.createUser({user:"myadmin",pwd:"123456",roles: [{role:"userAdminAnyDatabase",db:"admin"}]})

//查看用户情况
db.system.users.find()

(1)、如何删除一个用户?

db.dropUser("myroot")
db.dropUser("myadmin")

(2)、如何修改用户密码?

 db.changeUserPassword("myroot", "123456")
 db.changeUserPassword("myadmin", "123456")

第三步:测试用户

> use admin
switched to db admin
> db.auth("myroot","12345")
Error: Authentication failed.
0
> db.auth("myroot","123456")
1

第四步:创建普通用户

//切换到articledb
use articledb

//创建bobo
db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db: "articledb" }]})

//测试bobo
db.auth("bobo","123456")

第五步:关闭mongod服务

直接关掉窗口就行了

第六步:修改配置文件

添加以下代码

security:
   #开启授权认证
   authorization: enabled

第七步:登录测试

第一种:先登录,再认证

C:\DevTools\mongodb-win32-x86_64-2008plus-ssl-4.0.12\bin>mongo.exe --host=127.0.0.1 --port=27017
MongoDB shell version v4.0.12
connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("8b622b82-1a50-4a96-8916-cdc2b48dda45") }
MongoDB server version: 4.0.12
> use articledb
switched to db articledb
> db.auth("bobo","123456")
1
>

第二种:登录的同时认证

C:\DevTools\mongodb-win32-x86_64-2008plus-ssl-4.0.12\bin>mongo.exe --host=127.0.0.1 --port=27017 --authenticationDatabase=articledb -u bobo -p 123456
MongoDB shell version v4.0.12
connecting to: mongodb://127.0.0.1:27017/?authSource=articledb&gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("238f5a68-ac0d-4b65-b02a-56a4e1735727") }
MongoDB server version: 4.0.12
>

第七章 MongoDB备份与恢复

7.1、数据备份

语法格式:

mongodump.exe --host=数据库地址 --port=数据库端口 --authenticationDatabase=数据库名 -u 账户 -p 密码 -d 数据库名 -o 保存目录

案例演示:

C:\DevTools\mongodb-win32-x86_64-2008plus-ssl-4.0.12\bin>mongodump.exe --host=127.0.0.1 --port=27017 --authenticationDatabase=articledb -u bobo -p 123456 -d articledb -o "D:/"

7.2、数据恢复

语法格式:

C:\DevTools\mongodb-win32-x86_64-2008plus-ssl-4.0.12\bin>mongorestore.exe --host=数据库地址 --port=数据库端口 --authenticationDatabase=数据库名 -u 账户 -p 密码 -d 数据库名 --dir 导入目录 --drop

注意:–drop参数代表:恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,恢复后,备份后添加修改的数据都会被删除,慎用哦!

案例演示:

C:\DevTools\mongodb-win32-x86_64-2008plus-ssl-4.0.12\bin>mongorestore.exe --host=127.0.0.1 --port=27017 --authenticationDatabase=articledb -u bobo -p 123456 -d articledb --dir "D:/articledb" --drop

第八章 MongoDB副本集

8.1、安装环境

  • 操作系统:CentOS-6.10-x86_64-bin-DVD1.iso

  • 系统版本:桌面版(带图形化界面)

  • 内存大小:2GB

  • 硬盘大小:20GB

  • MongoDB:mongodb-linux-x86_64-4.0.10.tgz

  • 连接工具:SecureCRT7.0.0,连接会话已经设置编码为UTF-8,仿真环境设置为linux

    安装:yum install -y lrzsz
    上传:rz <敲回车>
    下载:sz 文件名
    

8.2、副本集介绍

MongoDB中的副本集(Replica Set)是一组维护相同数据集的mongod服务, 副本集可提供冗余和高可用性,是所有生产部署的基础。也可以说,副本集类似于有自动故障恢复功能的主从集群,通俗的讲,就是用多台机器进行同一数据的异步同步,从而使多台机器拥有同一数据的多个副本,并且当主库挂掉时在不需要用户干预的情况下自动切换其它备份服务器做主库,而且还可以利用副本服务器做只读服务器,实现读写分离,提高负载能力。

8.3、副本集架构

实现目标:一主一副本一仲裁、含有安全认证

image-20200822170216746

8.4、副本集搭建

第一步:安装软件

[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/
[root@caochenlei ~]# tar -zxvf mongodb-linux-x86_64-4.0.10.tgz
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/replica_sets/myrs_27017
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/replica_sets/myrs_27018
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/replica_sets/myrs_27019

第二步:创建目录

[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27017/data/db
[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27018/data/db
[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27019/data/db

[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27017/log
[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27018/log
[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27019/log

[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27017/config
[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27018/config
[root@caochenlei ~]# mkdir -p /mongodb/replica_sets/myrs_27019/config

第三步:编辑配置

[root@caochenlei ~]# vi mongod.conf
systemLog:
   destination: file
   #这里修改成你自己日志log目录地址,这里只能使用/千万不要用\
   path: "/mongodb/replica_sets/myrs_xxxxx/log/mongod.log"
   logAppend: true
net:
   port: xxxxx
   #填写虚拟机的IP地址
   bindIp: "192.168.206.128"
storage:
   #这里修改成你自己数据库db地址,这里只能使用/千万不要用\
   dbPath: "/mongodb/replica_sets/myrs_xxxxx/data/db"
   journal:
      enabled: true
processManagement:
   #是否以后台模式运行
   fork: true
   #进程PID
   pidFilePath: "/mongodb/replica_sets/myrs_xxxxx/log/mongod.pid"
replication:
   #副本集的名称
   replSetName: myrs

第四步:拷贝配置

[root@caochenlei ~]# sed 's/xxxxx/27017/g' mongod.conf > /mongodb/replica_sets/myrs_27017/config/mongod.conf
[root@caochenlei ~]# sed 's/xxxxx/27018/g' mongod.conf > /mongodb/replica_sets/myrs_27018/config/mongod.conf
[root@caochenlei ~]# sed 's/xxxxx/27019/g' mongod.conf > /mongodb/replica_sets/myrs_27019/config/mongod.conf

第五步:启动服务

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongod --config /mongodb/replica_sets/myrs_27017/config/mongod.conf
[root@caochenlei ~]# /mongodb/replica_sets/myrs_27018/bin/mongod --config /mongodb/replica_sets/myrs_27018/config/mongod.conf
[root@caochenlei ~]# /mongodb/replica_sets/myrs_27019/bin/mongod --config /mongodb/replica_sets/myrs_27019/config/mongod.conf

第六步:连接主节点

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongo --host=192.168.206.128 --port=27017
MongoDB shell version v4.0.10
connecting to: mongodb://192.168.206.128:27017/?gssapiServiceName=mongodb
Implicit session: session { "id" : UUID("dc3262f8-9f56-448b-a8c7-9abccba14442") }
MongoDB server version: 4.0.10
> 

第七步:初始化副本集

> rs.initiate()
{
        "info2" : "no configuration specified. Using a default configuration for the set",
        "me" : "192.168.206.128:27017",
        "ok" : 1,
        "operationTime" : Timestamp(1598110530, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598110530, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}
myrs:SECONDARY> 
myrs:PRIMARY> 

注意:myrs:SECONDARY> 回车变成主节点。

第八步:查看副本集配置

myrs:PRIMARY> rs.config()

配置说明:

  • “_id” : “myrs” :副本集的配置数据存储的主键值,默认就是副本集的名字
  • “members” :副本集的成员数组
  • “host” : (该节点数据库地址)
  • “arbiterOnly” : false(该成员不是仲裁节点)
  • “priority” : 1(优先级)
  • “settings” :副本集的参数配置

第九步:查看副本集状态

myrs:PRIMARY> rs.status()

状态说明:

  • “set” : “myrs” :副本集的名字
  • “myState” : 1:说明状态正常
  • “members” :副本集成员数组

第十步:添加副本节点

myrs:PRIMARY> rs.add("192.168.206.128:27018")

第十一步:添加仲裁节点

myrs:PRIMARY> rs.addArb("192.168.206.128:27019")

第十二步:查看副本集状态

myrs:PRIMARY> rs.status()

第十三步:测试主节点读写

myrs:PRIMARY> use articledb
switched to db articledb

myrs:PRIMARY> db.comment.insert({"articleid":"100000","content":"今天天气真好,阳光明媚","userid":"1001","nickname":"Rose","createdatetime":new Date()})
WriteResult({ "nInserted" : 1 })

myrs:PRIMARY> db.comment.find()
{ "_id" : ObjectId("5f413ea82b0bd854ea536d12"), "articleid" : "100000", "content" : "今天天气真好,阳光明媚", "userid" : "1001", "nickname" : "Rose", "createdatetime" : ISODate("2020-08-22T15:50:00.563Z") }

第十四步:测试副本节点读写

默认情况下,副本节点是没有读写权限的,可以增加读的权限,但需要进行设置。一般不设置写权限,这样就实现了读写分离的效果了。

先登录

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongo --host=192.168.206.128 --port=27018

再设置

myrs:SECONDARY> rs.slaveOk()

再测试

myrs:SECONDARY> use articledb
switched to db articledb

myrs:SECONDARY> db.comment.find()
{ "_id" : ObjectId("5f413ea82b0bd854ea536d12"), "articleid" : "100000", "content" : "今天天气真好,阳光明媚", "userid" : "1001", "nickname" : "Rose", "createdatetime" : ISODate("2020-08-22T15:50:00.563Z") }

第十五步:创建管理员

myrs:PRIMARY> use admin
switched to db admin

myrs:PRIMARY> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }

myrs:PRIMARY> exit

第十六步:生成KeyFile鉴权文件

[root@caochenlei ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@caochenlei ~]# chmod 400 ./mongo.keyfile 
[root@caochenlei ~]# ll mongo.keyfile
-r--------. 1 root root 122 8月  22 22:35 mongo.keyfile

第十七步:拷贝KeyFile鉴权文件

[root@caochenlei ~]# cp mongo.keyfile /mongodb/replica_sets/myrs_27017
[root@caochenlei ~]# cp mongo.keyfile /mongodb/replica_sets/myrs_27018
[root@caochenlei ~]# cp mongo.keyfile /mongodb/replica_sets/myrs_27019

第十八步:新增keyFile配置信息

修改27017的配置信息(最后一行新增以下代码):vi /mongodb/replica_sets/myrs_27017/config/mongod.conf

security:
   #KeyFile鉴权文件
   keyFile: "/mongodb/replica_sets/myrs_27017/mongo.keyfile"
   #开启授权认证
   authorization: enabled

修改27018的配置信息(最后一行新增以下代码):vi /mongodb/replica_sets/myrs_27018/config/mongod.conf

security:
   #KeyFile鉴权文件
   keyFile: "/mongodb/replica_sets/myrs_27018/mongo.keyfile"
   #开启授权认证
   authorization: enabled

修改27019的配置信息(最后一行新增以下代码):vi /mongodb/replica_sets/myrs_27019/config/mongod.conf

security:
   #KeyFile鉴权文件
   keyFile: "/mongodb/replica_sets/myrs_27019/mongo.keyfile"
   #开启授权认证
   authorization: enabled

第十九步:重启三个服务

先杀死

[root@caochenlei ~]# ps -ef | grep mongo
root       4600      1  2 Aug22 ?        00:00:36 /mongodb/replica_sets/myrs_27017/bin/mongod --config /mongodb/replica_sets/myrs_27017/config/mongod.conf
root       4632      1  2 Aug22 ?        00:00:36 /mongodb/replica_sets/myrs_27018/bin/mongod --config /mongodb/replica_sets/myrs_27018/config/mongod.conf
root       4662      1  1 Aug22 ?        00:00:31 /mongodb/replica_sets/myrs_27019/bin/mongod --config /mongodb/replica_sets/myrs_27019/config/mongod.conf

[root@caochenlei ~]# kill -9 4662 4632 4600

删文件

[root@caochenlei ~]# rm -f /mongodb/replica_sets/myrs_27017/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/replica_sets/myrs_27018/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/replica_sets/myrs_27019/data/db/*.lock

再修复

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongod --repair --dbpath=/mongodb/replica_sets/myrs_27017/data/db
[root@caochenlei ~]# /mongodb/replica_sets/myrs_27018/bin/mongod --repair --dbpath=/mongodb/replica_sets/myrs_27018/data/db
[root@caochenlei ~]# /mongodb/replica_sets/myrs_27019/bin/mongod --repair --dbpath=/mongodb/replica_sets/myrs_27019/data/db

再重启

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongod --config /mongodb/replica_sets/myrs_27017/config/mongod.conf
[root@caochenlei ~]# /mongodb/replica_sets/myrs_27018/bin/mongod --config /mongodb/replica_sets/myrs_27018/config/mongod.conf
[root@caochenlei ~]# /mongodb/replica_sets/myrs_27019/bin/mongod --config /mongodb/replica_sets/myrs_27019/config/mongod.conf

第二十步:创建普通用户

登录主节点

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongo --host=192.168.206.128 --port=27017

登录管理员,创建普通账户

myrs:PRIMARY> use admin
switched to db admin

myrs:PRIMARY> db.auth("myroot","123456")
1

myrs:PRIMARY> use articledb
switched to db articledb

myrs:PRIMARY> db.createUser({user: "bobo", pwd: "123456", roles: ["readWrite"]})
Successfully added user: { "user" : "bobo", "roles" : [ "readWrite" ] }

myrs:PRIMARY> exit

重新连接,使用普通账户登录

[root@caochenlei ~]# /mongodb/replica_sets/myrs_27017/bin/mongo --host=192.168.206.128 --port=27017

登录普通用户,然后查看comment集合中的所有文档

myrs:PRIMARY> use articledb
switched to db articledb

myrs:PRIMARY> db.auth("bobo","123456")
1

myrs:PRIMARY> db.comment.find()
{ "_id" : ObjectId("5f413ea82b0bd854ea536d12"), "articleid" : "100000", "content" : "今天天气真好,阳光明媚", "userid" : "1001", "nickname" : "Rose", "createdatetime" : ISODate("2020-08-22T15:50:00.563Z") }

8.5、副本集常用命令

(1)、使用默认的配置来初始化副本集:

rs.initiate()

(2)、查看副本集的配置内容:

rs.config()

(3)、查看副本集的状态:

rs.status()

(4)、添加副本节点:

rs.add("数据库地址:数据库端口")

(5)、添加仲裁节点:

rs.addArb("数据库地址:数据库端口")

(6)、移除副本节点或者仲裁节点:

rs.remove("数据库地址:数据库端口");

第九章 MongoDB分片集群

9.1、安装环境

  • 操作系统:CentOS-6.10-x86_64-bin-DVD1.iso

  • 系统版本:桌面版(带图形化界面)

  • 内存大小:2GB

  • 硬盘大小:20GB

  • MongoDB:mongodb-linux-x86_64-4.0.10.tgz

  • 连接工具:SecureCRT7.0.0,连接会话已经设置编码为UTF-8,仿真环境设置为linux

    安装:yum install -y lrzsz
    上传:rz <敲回车>
    下载:sz 文件名
    

9.2、分片集群介绍

分片(sharding)是一种跨多台机器分布数据的方法,MongoDB使用分片来支持具有非常大的数据集和高吞吐量操作的部署。换句话说:分片(sharding)是指将数据拆分,将其分散存在不同的机器上的过程。有时也用分区 (partitioning)来表示这个概念,将数据分散到不同的机器上,不需要功能强大的大型计算机就可以储存 更多的数据,处理更多的负载。

具有大型数据集或高吞吐量应用程序的数据库系统会挑战单个服务器的容量。例如,高查询率会耗尽服务器的CPU容量。工作集大小大于系统的RAM会强调磁盘驱动器的I/O容量。有两种解决系统增长的方法:垂直扩展和水平扩展。

垂直扩展意味着增加单个服务器的容量,例如使用更强大的CPU,添加更多RAM或增加存储空间量,可用技术的局限性可能会限制单个机器,此外,基于云的提供商基于可用的硬件配置具有硬性上限,结果,垂直缩放有实际的最大值。

水平扩展意味着划分系统数据集并加载多个服务器,添加其他服务器以根据需要增加容量,虽然单个机器的总体速度或容量可能不高,但每台机器处理整个工作负载的子集,可能提供比单个高速大容量服务器更高的效率,扩展部署容量只需要根据需要添加额外的服务器,这可能比单个机器的高端硬件的总体成本更低,而MongoDB支持通过分片进行水平扩展。

9.3、分片集群架构

实现目标:两个分片节点副本集(3+3)+一个配置节点副本集(3)+两个路由节点(2),共11个服务节点,均带安全认证。

image-20200823113349751

9.4、分片集群搭建

第一步:安装软件

[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/
[root@caochenlei ~]# tar -zxvf mongodb-linux-x86_64-4.0.10.tgz

#安装第一套分片节点副本集
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myshardrs01_27018
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myshardrs01_27118
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myshardrs01_27218

#安装第二套分片节点副本集
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myshardrs02_27318
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myshardrs02_27418
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myshardrs02_27518

#安装配置节点副本集
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myconfigrs_27019
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myconfigrs_27119
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/myconfigrs_27219

#安装路由节点副本集
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/mymongos_27017
[root@caochenlei ~]# cp -r mongodb-linux-x86_64-4.0.10 /mongodb/sharded_cluster/mymongos_27117

第二步:创建目录

#第一套分片节点副本集
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27018/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27118/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27218/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27018/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27118/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27218/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27018/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27118/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs01_27218/config

#第二套分片节点副本集
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27318/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27418/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27518/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27318/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27418/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27518/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27318/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27418/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myshardrs02_27518/config

#配置节点副本集
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27019/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27119/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27219/data/db
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27019/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27119/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27219/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27019/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27119/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/myconfigrs_27219/config

#路由节点副本集
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/mymongos_27017/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/mymongos_27117/log
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/mymongos_27017/config
[root@caochenlei ~]# mkdir -p /mongodb/sharded_cluster/mymongos_27117/config

第三步:编辑配置

主节点、副本节点、配置节点的配置信息:[root@caochenlei ~]# vi mongod.conf

注意:myname:代表集群中扮演的副本集名称、myrole:代表集群中扮演的角色名称、xxxxx:代表每个服务的端口号,一会使用替换全部替换掉

systemLog:
   destination: file
   #这里修改成你自己日志log目录地址,这里只能使用/千万不要用\
   path: "/mongodb/sharded_cluster/myname_xxxxx/log/mongod.log"
   logAppend: true
net:
   port: xxxxx
   #填写虚拟机的IP地址
   bindIp: localhost,192.168.206.128
storage:
   #这里修改成你自己数据库db地址,这里只能使用/千万不要用\
   dbPath: "/mongodb/sharded_cluster/myname_xxxxx/data/db"
   journal:
      enabled: true
processManagement:
   #是否以后台模式运行
   fork: true
   #进程PID
   pidFilePath: "/mongodb/sharded_cluster/myname_xxxxx/log/mongod.pid"
#security:
#   #KeyFile鉴权文件
#   keyFile: "/mongodb/sharded_cluster/myname_xxxxx/mongo.keyfile"
#   #开启授权认证
#   authorization: enabled
replication:
   #集群中扮演的副本集名称
   replSetName: myname
sharding:
   #集群中扮演的角色名称
   clusterRole: myrole

路由节点的配置信息:[root@caochenlei ~]# vi mongos.conf

注意:xxxxx:代表每个服务的端口号,一会使用替换全部替换掉

systemLog:
   destination: file
   #这里修改成你自己日志log目录地址,这里只能使用/千万不要用\
   path: "/mongodb/sharded_cluster/mymongos_xxxxx/log/mongod.log"
   logAppend: true
net:
   port: xxxxx
   #填写虚拟机的IP地址
   bindIp: localhost,192.168.206.128
processManagement:
   #是否以后台模式运行
   fork: true
   #进程PID
   pidFilePath: "/mongodb/sharded_cluster/mymongos_xxxxx/log/mongod.pid"
#security:
#   #KeyFile鉴权文件
#   keyFile: "/mongodb/sharded_cluster/mymongos_xxxxx/mongo.keyfile"
sharding:
   #集群中配置节点的所有服务地址
   configDB: myconfigrs/192.168.206.128:27019,192.168.206.128:27119,192.168.206.128:27219

第四步:复制配置

拷贝主节点、副本节点、配置节点的配置信息

#拷贝到主节点
[root@caochenlei ~]# sed "s/myname/myshardrs01/g;s/myrole/shardsvr/g;s/xxxxx/27018/g" mongod.conf > /mongodb/sharded_cluster/myshardrs01_27018/config/mongod.conf
[root@caochenlei ~]# sed "s/myname/myshardrs01/g;s/myrole/shardsvr/g;s/xxxxx/27118/g" mongod.conf > /mongodb/sharded_cluster/myshardrs01_27118/config/mongod.conf
[root@caochenlei ~]# sed "s/myname/myshardrs01/g;s/myrole/shardsvr/g;s/xxxxx/27218/g" mongod.conf > /mongodb/sharded_cluster/myshardrs01_27218/config/mongod.conf

#拷贝到副本节点
[root@caochenlei ~]# sed "s/myname/myshardrs02/g;s/myrole/shardsvr/g;s/xxxxx/27318/g" mongod.conf > /mongodb/sharded_cluster/myshardrs02_27318/config/mongod.conf
[root@caochenlei ~]# sed "s/myname/myshardrs02/g;s/myrole/shardsvr/g;s/xxxxx/27418/g" mongod.conf > /mongodb/sharded_cluster/myshardrs02_27418/config/mongod.conf
[root@caochenlei ~]# sed "s/myname/myshardrs02/g;s/myrole/shardsvr/g;s/xxxxx/27518/g" mongod.conf > /mongodb/sharded_cluster/myshardrs02_27518/config/mongod.conf

#拷贝到配置节点
[root@caochenlei ~]# sed "s/myname/myconfigrs/g;s/myrole/configsvr/g;s/xxxxx/27019/g" mongod.conf > /mongodb/sharded_cluster/myconfigrs_27019/config/mongod.conf
[root@caochenlei ~]# sed "s/myname/myconfigrs/g;s/myrole/configsvr/g;s/xxxxx/27119/g" mongod.conf > /mongodb/sharded_cluster/myconfigrs_27119/config/mongod.conf
[root@caochenlei ~]# sed "s/myname/myconfigrs/g;s/myrole/configsvr/g;s/xxxxx/27219/g" mongod.conf > /mongodb/sharded_cluster/myconfigrs_27219/config/mongod.conf

拷贝路由节点的配置信息

[root@caochenlei ~]# sed "s/xxxxx/27017/g" mongos.conf > /mongodb/sharded_cluster/mymongos_27017/config/mongos.conf
[root@caochenlei ~]# sed "s/xxxxx/27117/g" mongos.conf > /mongodb/sharded_cluster/mymongos_27117/config/mongos.conf

第五步:启动第一分片

启动:

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27018/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27018/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27118/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27118/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27218/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27218/config/mongod.conf

连接:使用客户端命令连接任意一个节点,但这里尽量要连接主节点!

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27018/bin/mongo --host=192.168.206.128 --port=27018

初始化副本集:

> rs.initiate()

添加副本节点:

myshardrs01:PRIMARY> rs.add("192.168.206.128:27118")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598162788, 2),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598162788, 2),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

添加仲裁节点:

myshardrs01:PRIMARY> rs.addArb("192.168.206.128:27218")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598163250, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598163250, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

查看分片集群情况:

myshardrs01:PRIMARY> rs.status()
myshardrs01:PRIMARY> exit

第六步:启动第二分片

启动:

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27318/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27318/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27418/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27418/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27518/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27518/config/mongod.conf

连接:使用客户端命令连接任意一个节点,但这里尽量要连接主节点!

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27318/bin/mongo --host=192.168.206.128 --port=27318

初始化副本集:

> rs.initiate()

添加副本节点:

myshardrs02:PRIMARY> rs.add("192.168.206.128:27418")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598163564, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598163564, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

添加仲裁节点:

myshardrs02:PRIMARY> rs.addArb("192.168.206.128:27518")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598163580, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598163580, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

查看分片集群情况:

myshardrs02:PRIMARY> rs.status()
myshardrs02:PRIMARY> exit

第七步:启动配置节点

启动:

[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27019/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27019/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27119/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27119/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27219/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27219/config/mongod.conf

连接:使用客户端命令连接任意一个节点,但这里尽量要连接主节点!

[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27019/bin/mongo --host=192.168.206.128 --port=27019

初始化副本集:

> rs.initiate()

添加副本节点:

myconfigrs:PRIMARY> rs.add("192.168.206.128:27119")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598164436, 1),
        "$gleStats" : {
                "lastOpTime" : {
                        "ts" : Timestamp(1598164436, 1),
                        "t" : NumberLong(1)
                },
                "electionId" : ObjectId("7fffffff0000000000000001")
        },
        "lastCommittedOpTime" : Timestamp(1598164430, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598164436, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

添加副本节点:

myconfigrs:PRIMARY> rs.add("192.168.206.128:27219")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598164454, 1),
        "$gleStats" : {
                "lastOpTime" : {
                        "ts" : Timestamp(1598164454, 1),
                        "t" : NumberLong(1)
                },
                "electionId" : ObjectId("7fffffff0000000000000001")
        },
        "lastCommittedOpTime" : Timestamp(1598164446, 1),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598164454, 1),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

查看配置集群情况:

myconfigrs:PRIMARY> rs.status()
myconfigrs:PRIMARY> exit

第八步:启动第一个路由节点

启动第一个路由节点:

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongos --config /mongodb/sharded_cluster/mymongos_27017/config/mongos.conf

连接第一个路由节点:

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongo --host=192.168.206.128 --port=27017

添加第一片分片:

mongos> sh.addShard("myshardrs01/192.168.206.128:27018,192.168.206.128:27118,192.168.206.128:27218")
{
        "shardAdded" : "myshardrs01",
        "ok" : 1,
        "operationTime" : Timestamp(1598165205, 3),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598165205, 3),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

添加第二片分片:

mongos> sh.addShard("myshardrs02/192.168.206.128:27318,192.168.206.128:27418,192.168.206.128:27518")
{
        "shardAdded" : "myshardrs02",
        "ok" : 1,
        "operationTime" : Timestamp(1598165244, 3),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598165244, 3),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

开启数据库分片功能:

mongos> sh.enableSharding("articledb")
{
        "ok" : 1,
        "operationTime" : Timestamp(1598165313, 5),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598165313, 5),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

开启集合分片功能:

(1)、分片规则一:哈希策略

对于基于哈希的分片,MongoDB计算一个字段的哈希值,并用这个哈希值来创建数据块,在使用基于哈希分片的系统中,拥有”相近”片键的文档很可能不会存储在同一个数据块中,因此数据的分离性更好一些。

使用nickname作为片键,根据其值的哈希值进行数据分片:

mongos> sh.shardCollection("articledb.comment",{"nickname":"hashed"}) 
{
        "collectionsharded" : "articledb.comment",
        "collectionUUID" : UUID("e493790d-43ac-450e-9c57-043e04b5ae6f"),
        "ok" : 1,
        "operationTime" : Timestamp(1598165446, 13),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598165446, 13),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

(2)、分片规则二:范围策略

对于基于范围的分片,MongoDB按照片键的范围把数据分成不同部分,假设有一个数字的片键:想象一个从负无穷到正无穷的直线,每一个片键的值都在直线上画了一个点,MongoDB把这条直线划分为更短的不重叠的片段并称之为数据块,每个数据块包含了片键在一定范围内的数据。在使用片键做范围划分的系统中,拥有”相近”片键的文档很可能存储在同一个数据块中,因此也会存储在同 一个分片中。

使用作者年龄字段作为片键,根据其值进行数据分片:

mongos> sh.shardCollection("articledb.author",{"age":1})
{
        "collectionsharded" : "articledb.author",
        "collectionUUID" : UUID("e079d412-fe47-4fa6-a1cd-144224836f3c"),
        "ok" : 1,
        "operationTime" : Timestamp(1598165482, 17),
        "$clusterTime" : {
                "clusterTime" : Timestamp(1598165482, 17),
                "signature" : {
                        "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
                        "keyId" : NumberLong(0)
                }
        }
}

注意:

  • 一个集合只能指定一个片键,否则报错
  • 一旦对一个集合分片,分片键和分片值就不可改变
  • 根据age索引进行分配数据

查看分片状态:

mongos> sh.status()

第九步:分片效果测试

  • 测试哈希策略

登录到第一个路由节点,写入100条数据,然后退出

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongo --host=192.168.206.128 --port=27017
mongos> use articledb
switched to db articledb
mongos> for(var i=1;i<=1000;i++) {db.comment.insert({_id:i+"",nickname:"BoBo"+i})}
WriteResult({ "nInserted" : 1 })
mongos> db.comment.count() 
1000
mongos> exit

登录第一个分片,查看保存数据量

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27018/bin/mongo --host=192.168.206.128 --port=27018
myshardrs01:PRIMARY> use articledb
switched to db articledb
myshardrs01:PRIMARY> db.comment.count()
507
myshardrs01:PRIMARY> exit

登录到第二个分片,查看保存数据量

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27318/bin/mongo --host=192.168.206.128 --port=27318
myshardrs02:PRIMARY> use articledb
switched to db articledb
myshardrs02:PRIMARY> db.comment.count()
493
myshardrs02:PRIMARY> exit
  • 测试范围策略

登录到第一个路由节点,写入20000条数据,然后退出

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongo --host=192.168.206.128 --port=27017
mongos> use articledb
switched to db articledb
mongos> for(var i=1;i<=20000;i++) {db.author.save({"age":NumberInt(i%100)})}
WriteResult({ "nInserted" : 1 })
mongos> db.author.count()
20000
mongos> exit

登录第一个分片,查看保存数据量

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27018/bin/mongo --host=192.168.206.128 --port=27018
myshardrs01:PRIMARY> use articledb
switched to db articledb
myshardrs01:PRIMARY> db.author.count()
0
myshardrs01:PRIMARY> exit

登录到第二个分片,查看保存数据量

[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27318/bin/mongo --host=192.168.206.128 --port=27318
myshardrs02:PRIMARY> use articledb
switched to db articledb
myshardrs02:PRIMARY> db.author.count()
20000
myshardrs02:PRIMARY> exit

我们发现,好像并没有分片,这是因为数据块(chunk)没有填满,默认的数据块尺寸(chunksize)是64M,填满后才会考虑向其它片的数据块填充数据,因此,为了测试,可以将其改小,这里改为1M,操作如下:

测试前改这样:

use config
db.settings.save({_id:"chunksize",value:1})

测试完改回来:

use config
db.settings.save({_id:"chunksize",value:64})

注意:要先改小,再设置分片。为了测试,可以先删除集合,重新建立集合的分片策略,再插入数据测试即可。

第十步:启动第二个路由节点

启动第二个路由节点:

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27117/bin/mongos --config /mongodb/sharded_cluster/mymongos_27117/config/mongos.conf

连接第二个路由节点:

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27117/bin/mongo --host=192.168.206.128 --port=27117

查看分片状态:

mongos> sh.status()

第十一步:创建管理员

[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongo --host=192.168.206.128 --port=27017
mongos> use admin
switched to db admin

mongos> db.createUser({user:"myroot",pwd:"123456",roles:["root"]})
Successfully added user: { "user" : "myroot", "roles" : [ "root" ] }

mongos> exit

第十二步:生成KeyFile鉴权文件

[root@caochenlei ~]# openssl rand -base64 90 -out ./mongo.keyfile
[root@caochenlei ~]# chmod 400 ./mongo.keyfile 
[root@caochenlei ~]# ll mongo.keyfile
-r--------. 1 root root 122 8月  22 22:35 mongo.keyfile

第十三步:拷贝KeyFile鉴权文件

[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myshardrs01_27018/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myshardrs01_27118/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myshardrs01_27218/mongo.keyfile

[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myshardrs02_27318/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myshardrs02_27418/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myshardrs02_27518/mongo.keyfile

[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myconfigrs_27019/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myconfigrs_27119/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/myconfigrs_27219/mongo.keyfile

[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/mymongos_27017/mongo.keyfile
[root@caochenlei ~]# cp mongo.keyfile /mongodb/sharded_cluster/mymongos_27117/mongo.keyfile

第十四步:新增keyFile配置信息

取消这11台配置文件中的安全注释,它们在每一台对应的config文件夹中

security:
   #KeyFile鉴权文件
   keyFile: ""
   #开启授权认证
   authorization: enabled
#取消主节点的安全授权注释
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myshardrs01_27018/config/mongod.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myshardrs01_27118/config/mongod.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myshardrs01_27218/config/mongod.conf

#取消副本节点的安全授权注释
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myshardrs02_27318/config/mongod.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myshardrs02_27418/config/mongod.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myshardrs02_27518/config/mongod.conf

#取消配置节点的安全授权注释
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myconfigrs_27019/config/mongod.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myconfigrs_27119/config/mongod.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/myconfigrs_27219/config/mongod.conf

#取消路由节点的安全授权注释
[root@caochenlei ~]# vi /mongodb/sharded_cluster/mymongos_27017/config/mongos.conf
[root@caochenlei ~]# vi /mongodb/sharded_cluster/mymongos_27117/config/mongos.conf

第十五步:重启所有服务

先杀死

[root@caochenlei ~]# ps -ef | grep mongo
root       4523      1  2 14:15 ?        00:04:36 /mongodb/sharded_cluster/myshardrs01_27018/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27018/config/mongod.conf
root       4602      1  2 14:15 ?        00:04:34 /mongodb/sharded_cluster/myshardrs01_27118/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27118/config/mongod.conf
root       4747      1  2 16:49 ?        00:00:22 /mongodb/sharded_cluster/myshardrs01_27218/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27218/config/mongod.conf
root       4776      1  4 14:18 ?        00:06:52 /mongodb/sharded_cluster/myshardrs02_27318/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27318/config/mongod.conf
root       4985      1  4 14:18 ?        00:06:51 /mongodb/sharded_cluster/myshardrs02_27418/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27418/config/mongod.conf
root       5022      1  2 16:49 ?        00:00:21 /mongodb/sharded_cluster/myshardrs02_27518/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27518/config/mongod.conf
root       5058      1  2 14:32 ?        00:03:59 /mongodb/sharded_cluster/myconfigrs_27019/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27019/config/mongod.conf
root       5992      1  2 14:32 ?        00:03:37 /mongodb/sharded_cluster/myconfigrs_27119/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27119/config/mongod.conf
root       6742      1  2 14:32 ?        00:03:36 /mongodb/sharded_cluster/myconfigrs_27219/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27219/config/mongod.conf
root       6787      1  1 16:52 ?        00:00:11 /mongodb/sharded_cluster/mymongos_27017/bin/mongos --config /mongodb/sharded_cluster/mymongos_27017/config/mongos.conf
root       6860      1  1 15:36 ?        00:01:18 /mongodb/sharded_cluster/mymongos_27117/bin/mongos --config /mongodb/sharded_cluster/mymongos_27117/config/mongos.conf

[root@caochenlei ~]# kill -9 6860 6787 6742 5992 5058 5022 4985 4776 4747 4602 4523

删文件

#第一套分片节点副本集
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myshardrs01_27018/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myshardrs01_27118/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myshardrs01_27218/data/db/*.lock

#第二套分片节点副本集
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myshardrs02_27318/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myshardrs02_27418/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myshardrs02_27518/data/db/*.lock

#配置节点副本集
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myconfigrs_27019/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myconfigrs_27119/data/db/*.lock
[root@caochenlei ~]# rm -f /mongodb/sharded_cluster/myconfigrs_27219/data/db/*.lock

再修复

#第一套分片节点副本集
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27018/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs01_27018/data/db
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27118/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs01_27118/data/db
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27218/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs01_27218/data/db

#第二套分片节点副本集
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27318/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs02_27318/data/db
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27418/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs02_27418/data/db
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27518/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myshardrs02_27518/data/db

#配置节点副本集
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27019/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myconfigrs_27019/data/db
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27119/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myconfigrs_27119/data/db
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27219/bin/mongod --repair --dbpath=/mongodb/sharded_cluster/myconfigrs_27219/data/db

再重启:必须依次启动配置节点、分片节点、路由节点

注意:启动如果遇到about to fork child process, waiting until server is ready for connections,这也许是一个BUG,情况未知!

#启动配置节点副本集
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27019/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27019/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27119/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27119/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myconfigrs_27219/bin/mongod --config /mongodb/sharded_cluster/myconfigrs_27219/config/mongod.conf

#启动第一套分片节点副本集
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27018/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27018/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27118/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27118/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs01_27218/bin/mongod --config /mongodb/sharded_cluster/myshardrs01_27218/config/mongod.conf

#启动第二套分片节点副本集
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27318/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27318/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27418/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27418/config/mongod.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/myshardrs02_27518/bin/mongod --config /mongodb/sharded_cluster/myshardrs02_27518/config/mongod.conf

#启动路由节点
[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongos --config /mongodb/sharded_cluster/mymongos_27017/config/mongos.conf
[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27117/bin/mongos --config /mongodb/sharded_cluster/mymongos_27117/config/mongos.conf

第十六步:创建普通账号

#登录到第一个路由节点
[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongo --host=192.168.206.128 --port=27017

mongos> use admin
switched to db admin

mongos> db.auth("myroot","123456")
1

mongos> use articledb
switched to db articledb

mongos> db.createUser({user: "bobo", pwd: "123456", roles: [{ role: "readWrite", db: "articledb" }]})
Successfully added user: {
        "user" : "bobo",
        "roles" : [
                {
                        "role" : "readWrite",
                        "db" : "articledb"
                }
        ]
}

mongos> exit

第十七步:登录普通账号

#登录到第一个路由节点
[root@caochenlei ~]# /mongodb/sharded_cluster/mymongos_27017/bin/mongo --host=192.168.206.128 --port=27017

mongos> use articledb
switched to db articledb

mongos> db.auth("bobo","123456")
1

mongos> exit

9.5、分片集群常用命令

(1)、使用默认的配置来初始化副本集:

rs.initiate()

(2)、查看副本集的配置内容:

rs.config()

(3)、查看副本集的状态:

rs.status()

(4)、添加副本节点:

rs.add("数据库地址:数据库端口")

(5)、添加仲裁节点:

rs.addArb("数据库地址:数据库端口")

(6)、移除副本节点或者仲裁节点:

rs.remove("数据库地址:数据库端口");

(7)、添加分片:

sh.addShard("分片名称/数据库地址:数据库端口,数据库地址:数据库端口,数据库地址:数据库端口,...") 

(8)、移除分片:

use admin
db.runCommand({ removeShard: "分片名称" })

注意:如果只剩下最后一个shard,是无法删除的,移除时会自动转移分片数据,这需要一个时间过程。

(9)、查看分片状态:

sh.status()

(10)、开启数据库分片:

sh.enableSharding("数据库名")

(11)、开启集合分片:

sh.shardCollection("数据库名.集合名", "片键", "是否是唯一索引,默认是false,哈希策略片键不支持唯一索引")

(12)、显示集群的详细信息:

use admin
db.printShardingStatus()

(13)、查看均衡器是否工作:

sh.isBalancerRunning()

(14)、查看当前Balancer状态:

 sh.getBalancerState()

第十章 MongoDB的Java连接

10.1、确定驱动

jar包版本与MongoDB版本对应关系如下图:

img

10.2、创建工程

  • 第一步:创建一个名字叫MongoDBDemo的Java工程
  • 第二步:创建一个lib文件夹,将所需依赖放进去,然后Build Path一下
    • bson-3.11.0.jar
    • mongodb-driver-3.11.0.jar
    • mongodb-driver-core-3.11.0.jar
  • 第三步:创建一个测试包,名字叫com.caochenlei.mongodb.demo
  • 第四步:添加Junit4单元测试

10.3、连接单实例版

MongoDBSingle.java(全路径:/MongoDBDemo/src/com/caochenlei/mongodb/demo/MongoDBSingle.java)

@Test
public void testLink() {
	// 这里的地址代表单机实例的地址
	MongoClientURI mongoClientURI = new MongoClientURI("mongodb://bobo:123456@localhost:27017/articledb");
	MongoClient mongoClient = new MongoClient(mongoClientURI);
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	MongoCollection<Document> comment = articledb.getCollection("comment");
	// 插入一条文档
	Document doc = new Document();
	doc.append("articleid", "10086");
	doc.append("nickname", "张三");
	doc.append("content", "床前明月光,疑是地上霜!");
	doc.append("likenum", 1000);
	comment.insertOne(doc);
	// 查看所有文档
	MongoCursor<Document> cursor = comment.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
	// 释放所有资源
	mongoClient.close();
}

10.4、连接副本集版

MongoDBReplicaSet.java(全路径:/MongoDBDemo/src/com/caochenlei/mongodb/demo/MongoDBReplicaSet.java)

@Test
public void testLink() {
	// 这里的地址代表副本集所有节点的地址
	MongoClientURI mongoClientURI = new MongoClientURI("mongodb://bobo:123456@192.168.206.128:27017,192.168.206.128:27018,192.168.206.128:27019/articledb?connect=replicaSet&slaveOk=true&replicaSet=myrs");
	MongoClient mongoClient = new MongoClient(mongoClientURI);
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	MongoCollection<Document> comment = articledb.getCollection("comment");
	// 插入一条文档
	Document doc = new Document();
	doc.append("articleid", "10086");
	doc.append("nickname", "张三");
	doc.append("content", "床前明月光,疑是地上霜!");
	doc.append("likenum", 1000);
	comment.insertOne(doc);
	// 查看所有文档
	MongoCursor<Document> cursor = comment.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
	// 释放所有资源
	mongoClient.close();
}

10.5、连接分片集群版

MongoDBCluster.java(全路径:/MongoDBDemo/src/com/caochenlei/mongodb/demo/MongoDBCluster.java)

@Test
public void testLink() {
	//这里的地址代表路由节点的地址
	MongoClientURI mongoClientURI = new MongoClientURI("mongodb://bobo:123456@192.168.206.128:27017,192.168.206.128:27117/articledb");
	MongoClient mongoClient = new MongoClient(mongoClientURI);
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	MongoCollection<Document> comment = articledb.getCollection("comment");
	// 插入一条文档
	Document doc = new Document();
	doc.append("articleid", "10086");
	doc.append("nickname", "张三");
	doc.append("content", "床前明月光,疑是地上霜!");
	doc.append("likenum", 1000);
	comment.insertOne(doc);
	// 查看所有文档
	MongoCursor<Document> cursor = comment.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
	// 释放所有资源
	mongoClient.close();
}

第十一章 MongoDB的JavaAPI

MongoDBDemo.java(全路径:/MongoDBDemo/src/com/caochenlei/mongodb/demo/MongoDBDemo.java)

初始化和关闭

private MongoClientURI mongoClientURI;
private MongoClient mongoClient;

@Before
public void init() {
	mongoClientURI = new MongoClientURI("mongodb://bobo:123456@localhost:27017/articledb");
	mongoClient = new MongoClient(mongoClientURI);
}

@After
public void drop() {
	mongoClient.close();
}

11.1、创建数据库

/**
 * 创建数据库
 */
@Test
public void test1() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	System.out.println(articledb);
}

11.2、查看数据库

/**
 * 查看数据库
 */
@Test
public void test2() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	String name = articledb.getName();
	System.out.println(name);
}

11.3、删除数据库

/**
 * 删除数据库
 */
@Test
public void test3() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 当前用户需要有删除数据库的权限
	articledb.drop();
}

11.4、创建集合

/**
 * 创建集合
 */
@Test
public void test4() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	System.out.println(users);
}

11.5、查看集合

/**
 * 查看集合
 */
@Test
public void test5() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	MongoNamespace namespace = users.getNamespace();
	System.out.println(namespace);
}

11.6、删除集合

/**
 * 删除集合
 */
@Test
public void test6() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	users.drop();
}

11.7、插入文档

插入一条:

/**
 * 插入文档:插入一条
 */
@Test
public void test7() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	Document user = new Document();
	user.append("username", "张三");
	user.append("password", "123456");
	user.append("age", 18);
	users.insertOne(user);
}

插入多条:

/**
 * 插入文档:插入多条
 */
@Test
public void test8() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	Document user1 = new Document();
	user1.append("username", "李四");
	user1.append("password", "123456");
	user1.append("age", 19);
	Document user2 = new Document();
	user2.append("username", "王五");
	user2.append("password", "123456");
	user2.append("age", 20);
	Document user3 = new Document();
	user3.append("username", "赵六");
	user3.append("password", "123456");
	user3.append("age", 21);
	List<Document> list = new ArrayList<Document>();
	list.add(user1);
	list.add(user2);
	list.add(user3);
	users.insertMany(list);
}

11.8、查看文档

查看全部:

/**
 * 查看文档:查看全部
 */
@Test
public void test9() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 查看全部
	MongoCursor<Document> cursor = users.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

条件查询:

/**
 * 查看文档:条件查询
 * 常见操作符:等于、$ne$gte$lte$gt$lt
 */
@Test
public void test10() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 条件查询:查询年龄不等于20岁的用户信息
	BasicDBObject searchCond = new BasicDBObject();
	searchCond.append("age", new BasicDBObject("$ne", 20));
	MongoCursor<Document> cursor = users.find(searchCond).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

连接查询:

/**
 * 查看文档:连接查询:AND查询
 * 常见连接:AND、OR
 */
@Test
public void test11() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 连接查询:查询年龄大于18岁并且小于21岁的用户信息
	BasicDBList condList = new BasicDBList();
	condList.add(new BasicDBObject("age", new BasicDBObject("$gt", 18)));
	condList.add(new BasicDBObject("age", new BasicDBObject("$lt", 20)));
	BasicDBObject searchCond = new BasicDBObject();
	searchCond.put("$and", condList);
	MongoCursor<Document> cursor = users.find(searchCond).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

/**
 * 查看文档:连接查询:OR查询
 * 常见连接:AND、OR
 */
@Test
public void test12() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 连接查询:查询年龄小于等于18岁或者大于等于21岁的用户信息
	BasicDBList condList = new BasicDBList();
	condList.add(new BasicDBObject("age", new BasicDBObject("$lte", 18)));
	condList.add(new BasicDBObject("age", new BasicDBObject("$gte", 21)));
	BasicDBObject searchCond = new BasicDBObject();
	searchCond.put("$or", condList);
	MongoCursor<Document> cursor = users.find(searchCond).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

类型查询:

/**
 * 查看文档:类型查询
 */
@Test
public void test13() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 类型查询:查询所有用户名是字符串类型的用户信息
	BasicDBObject searchCond = new BasicDBObject();
	searchCond.append("username", new BasicDBObject("$type", "string"));
	MongoCursor<Document> cursor = users.find(searchCond).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

分页查询:

/**
 * 查看文档:分页查询
 */
@Test
public void test14() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 分页查询:跳过第一条,查询两条数据
	MongoCursor<Document> cursor = users.find().skip(1).limit(2).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

投影查询:

/**
 * 查看文档:投影查询
 */
@Test
public void test15() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 投影查询:只显示所有用户的用户名和_id信息
	MongoCursor<Document> cursor = users.find().projection(new BasicDBObject("username", 1)).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

排序查询:

/**
 * 查看文档:排序查询
 * 排序规则:1(升序)、-1(降序)
 */
@Test
public void test16() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 排序查询:按照用户年龄降序排序
	MongoCursor<Document> cursor = users.find().sort(new BasicDBObject("age", -1)).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

统计查询:

/**
 * 查看文档:统计查询
 */
@Test
public void test17() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 统计查询:查看密码为123456的一共有多少人
	BasicDBObject filter = new BasicDBObject("password", "123456");
	long count = users.countDocuments(filter);
	System.out.println(count);
}

包含查询:

/**
 * 查看文档:包含查询
 * 常见操作符:$in、$nin
 */
@Test
public void test18() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 包含查询:查询username = 张三、李四、王五的信息
	List<String> searchList = new ArrayList<String>();
	searchList.add("张三");
	searchList.add("李四");
	searchList.add("王五");
	BasicDBObject searchCond = new BasicDBObject("username", new BasicDBObject("$in", searchList));
	MongoCursor<Document> cursor = users.find(searchCond).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

正则查询:

/**
 * 查看文档:正则查询
 */
@Test
public void test19() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	/**
	 * 左匹配:Pattern.compile("^王.*$", Pattern.CASE_INSENSITIVE);
	 * 右匹配:Pattern.compile("^.*王$", Pattern.CASE_INSENSITIVE);
	 * 完全匹配:Pattern.compile("^王$", Pattern.CASE_INSENSITIVE);
	 * 模糊匹配:Pattern.compile("^.*王.*$", Pattern.CASE_INSENSITIVE);
	 */
	// 正则查询:查询所有以王开头的用户姓名
	Pattern pattern = Pattern.compile("^王.*$", Pattern.CASE_INSENSITIVE);
	BasicDBObject searchCond = new BasicDBObject("username", new BasicDBObject("$regex", pattern));
	MongoCursor<Document> cursor = users.find(searchCond).iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

11.9、修改文档

更新一条:

/**
 * 修改文档:更新一条
 */
@Test
public void test20() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 更新一条:将张三更改为张三三
	BasicDBObject updateOld = new BasicDBObject("username", "张三");
	BasicDBObject updateNew = new BasicDBObject("$set", new BasicDBObject("username", "张三三"));
	users.updateOne(updateOld, updateNew);
	// 查看全部
	MongoCursor<Document> cursor = users.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

更新多条:

/**
 * 修改文档:更新多条
 */
@Test
public void test21() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 更新多条:将密码为123456的用户全部重置为abcdef
	BasicDBObject updateOld = new BasicDBObject("password", "123456");
	BasicDBObject updateNew = new BasicDBObject("$set", new BasicDBObject("password", "abcdef"));
	users.updateMany(updateOld, updateNew);
	// 查看全部
	MongoCursor<Document> cursor = users.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

更新多个字段:

/**
 * 修改文档:更新多个字段
 */
@Test
public void test22() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 更新多个字段:将密码为abcdef的用户全部重置为123456并且年龄全部置为30岁
	BasicDBObject updateOld = new BasicDBObject("password", "abcdef");
	BasicDBObject updateNew = new BasicDBObject("$set", new BasicDBObject("password", "123456").append("age", 30));
	users.updateMany(updateOld, updateNew);
	// 查看全部
	MongoCursor<Document> cursor = users.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

11.10、删除文档

删除一条:

/**
 * 删除文档:删除一条
 */
@Test
public void test23() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 删除一条:将张三三删除
	BasicDBObject cond = new BasicDBObject("username", "张三三");
	users.deleteOne(cond);
	// 查看全部
	MongoCursor<Document> cursor = users.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}

删除多条:

/**
 * 删除文档:删除多条
 */
@Test
public void test24() {
	// 如果存在articledb,返回articledb,如果不存在articledb,创建articledb
	MongoDatabase articledb = mongoClient.getDatabase("articledb");
	// 如果存在users,返回users,如果不存在,创建users
	MongoCollection<Document> users = articledb.getCollection("users");
	// 删除多条:将密码为123456的用户全部删除
	BasicDBObject cond = new BasicDBObject("password", "123456");
	users.deleteMany(cond);
	// 查看全部
	MongoCursor<Document> cursor = users.find().iterator();
	while (cursor.hasNext()) {
		System.out.println(cursor.next());
	}
}
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:设计师小姐姐 返回首页