0


MongoDB详解,用心看这篇就够了【重点】

1.1

MongoDB

概述

MongoDB

是一个基于分布式文件存储的数据库。由

C++

语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

MongoDB

是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。

它支持的数据结构非常松散,是类似

json

bson

格式,因此可以存储比较复杂的数据类型。

Mongo

最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

MongoDB

服务端可运行在

Linux

Windows

平台,支持

32

位和

64

位应用,默认端口为

27017


推荐运行在

64

位平台,因为

MongoD

B在

32

位模式运行时支持的最大文件尺寸为

2

GB。

1.2

MongoDB

主要特点

1.2.1 文档

MongoDB

中的记录是一个文档,它是由字段和值对组成的数据结构。
多个键及其关联的值有序地放在一起就构成了文档。

MongoDB

文档类似于

JSON

对象。字段的值可以包括其他文档,数组和文档数组。
在这里插入图片描述

{“greeting”:“hello,world”}

这个文档只有一个键

“greeting”

,对应的值为

“hello,world”

。多数情况下,文档比这个更复杂,它包含多个键/值对。

例如:

{“greeting”:“hello,world”,“foo”: 3}

文档中的键/值对是有序的,下面的文档与上面的文档是完全不同的两个文档。

{“foo”: 3 ,“greeting”:“hello,world”}

文档中的值不仅可以是双引号中的字符串,也可以是其他的数据类型,例如,整型、布尔型等,也可以是另外一个文档,即文档可以嵌套。文档中的键类型只能是字符串

使用文档的优点是:

  • 文档(即对象)对应于许多编程语言中的本机数据类型
  • 嵌入式文档和数组减少了对昂贵连接的需求
  • 动态模式支持流畅的多态性

1.3.2 集合

集合就是一组文档,类似于关系数据库中的表。

集合是无模式的,集合中的文档可以是各式各样的。例如,

{“hello,word”:“Mike”}

{“foo”: 3}

,它们的键不同,值的类型也不同,但是它们可以存放在同一个集合中,也就是不同模式的文档都可以放在同一个集合中。

既然集合中可以存放任何类型的文档,那么为什么还需要使用多个集合?
这是因为所有文档都放在同一个集合中,无论对于开发者还是管理员,都很难对集合进行管理,而且这种情形下,对集合的查询等操作效率都不高。所以在实际使用中,往往将文档分类存放在不同的集合中。
例如,对于网站的日志记录,可以根据日志的级别进行存储,

Info

级别日志存放在

Info

集合中,

Debug

级别日志存放在

Debug

集合中,这样既方便了管理,也提供了查询性能。
但是需要注意的是,这种对文档进行划分来分别存储并不是

MongoDB

的强制要求,用户可以灵活选择。

可以使用

“.”

按照命名空间将集合划分为子集合。
例如,对于一个博客系统,可能包括

blog.user

blog.article

两个子集合,这样划分只是让组织结构更好一些,

blog

集合和

blog.user

blog.article

没有任何关系。虽然子集合没有任何特殊的地方,但是使用子集合组织数据结构清晰,这也是

MongoDB

推荐的方法。

1.3.3 数据库

MongoDB

中多个文档组成集合,多个集合组成数据库。

一个

MongoDB

实例可以承载多个数据库。它们之间可以看作相互独立,每个数据库都有独立的权限控制。在磁盘上,不同的数据库存放在不同的文件中。

MongoDB

中存在以下系统数据库。

  • Admin 数据库:一个权限数据库,如果创建用户的时候将该用户添加到admin 数据库中,那么该用户就自动继承了所有数据库的权限。
  • Local 数据库:这个数据库永远不会被复制,可以用来存储本地单台服务器的任意集合。
  • Config 数据库:当MongoDB 使用分片模式时,config数据库在内部使用,用于保存分片的信息。

1.3.4 数据模型

一个

MongoDB

实例可以包含一组数据库,一个

DataBase

可以包含一组

Collection

(集合),一个集合可以包含一组

Document

(文档)。

一个

Document

包含一组

field

(字段),每一个字段都是一个

key/value pair
  • key: 必须为字符串类型
  • value:可以包含如下类型 - 基本类型,例如,string,int,float,timestamp,binary 等类型- 一个document- 数组类型

1.4

Windows

安装

MongoDB

1.4.1 下载

MongoDB
MongoDB

提供了可用于

32

位系统和

64

位系统的预编译二进制包(新版本没有了

32

位系统的安装文件),你可以进入

MongoDB

官网下载安装,

MongoDB

的预编译二进制包的下载地址为:

https://www.mongodb.com/download-center/community

,打开之后会看到如下图,直接点击

Download

下载即可,也可以在

Version

中选择你想要的版本:
在这里插入图片描述

1.4.2 安装

MongoDB

双击打开文件进行安装,在安装过程中,可以通过点击 “

Custom

(自定义)” 按钮来设置你的安装目录。
在这里插入图片描述
这里我选择安装在

E:\MongoDB

这个目录下(安装目录会影响我们后面的配置)
在这里插入图片描述
这里选择直接

next

在这里插入图片描述
这里安装

"Install MongoDB Compass"

不勾选,否则可能要很长时间都一直在执行安装,

MongoDB Compass

是一个图形界面管理工具,这里不安装也是没有问题的,可以自己去下载一个图形界面管理工具,比如

Robo3T


在这里插入图片描述
之后稍微等待一会就安装好了。

1.4.3 配置

MongoDB
MongoDB

的安装过程是很简单的,但是配置就比较麻烦了,可能会遇到各种各样的问题,需要你有足够的耐心和仔细。

首先要在

MongoDB

data

文件夹里新建一个

db

文件夹和一个

log

文件夹:
在这里插入图片描述
然后在log文件夹下新建一个mongo.log:
在这里插入图片描述
然后将

E:\MongoDB\bin

添加到环境变量

path

中,此时打开

cmd

窗口运行一下

mongo

命令,出现如下情况:
在这里插入图片描述
这是为什么呢?这是因为我们还没有启动

MongoDB

服务,自然也就连接不上服务了。那要怎么启动呢?在

cmd

窗口中运行如下命令:

 mongod --dbpath E:\MongoDB\data\db

需要注意的是:如果你没有提前创建

db

文件夹,是无法启动成功的。运行成功之后,我们打开浏览器,输入

127.0.0.1:27017

,看到如下图,就说明

MongoDB

服务已经成功启动了。
在这里插入图片描述
但是如果每次都要这么启动服务的话也太麻烦了吧,这里你可以选择设置成开机自启动,也可以选择用命令

net start mongodb

来手动启动,这里我选择使用后者,具体方法如下。

还是打开

cmd

窗口,不过这次是以管理员身份运行,然后输入如下命令:

mongod --dbpath "E:\MongoDB\data\db" --logpath "E:\MongoDB\data\log\mongo.log" -install -serviceName "MongoDB"

如果没有报错的话就说明成功添加到服务里了,可以使用

win+R

然后输入

services.msc

命令进行查看:
在这里插入图片描述
默认是自动运行的,这里我选择把它改成手动的。然后在

cmd

窗口中运行

net start mongodb


在这里插入图片描述
怎么解决呢?两个步骤:
1)运行

sc delete mongodb

删除服务;
2)再运行一次配置服务的命令:

mongod --dbpath "E:\MongoDB\data\db" --logpath "E:\MongoDB\data\log\mongo.log" -install -serviceName "MongoDB"

然后再运行

net start mongodb

,服务启动成功:
在这里插入图片描述
可能遇到的问题:
1、

mongod

不是内部或外部命令
出现这种问题说明你没有把

bin

目录添加到环境变量之中,重新添加一下即可解决。

2、服务名无效
首先是看你输入的服务名称是否有误,然后再查看本地服务中有没有

MongoDB

服务,如果没有服务,则运行命令添加服务即可。

3、发生服务特定错误:

100

删除

db

文件夹下的

mongod.lock

storage.bson

两个文件,若删除完之后仍然出现这种问题,用

sc delete mongodb

删除服务,再配置一下服务就能解决了。

1.4.4 安装一个可视化工具

官网下载

RoBo 3T(Robomongo is now Robo 3T)

下载地址:

https://robomongo.org/download

在这里插入图片描述
在这里插入图片描述
双击安装包安装,修改安装路径,不停下一步,点击安装。
在这里插入图片描述
打开后,有一个填信息的页面,

name

email

,暂时不用管,直接

finish


启动

MongoDB

服务。
点击弹出框中的

create

,创建新连接,可以修改连接名

name

,连接

IP

(下图

IP

为本地

IP

),端口(默认)
在这里插入图片描述
连接成功后,右击

localhost

,选择

create Database

,创建数据库
在这里插入图片描述
创建数据库

firstTest

,然后右击

firstTest

,选择

open Shell

,开始进行

shell

命令来创建数据库中的集合和文档。
在这里插入图片描述

1.5

Linux

安装

MongoDB

1.5.1 下载

MongoDB

官方下载地址:

https://www.mongodb.com/download-center/community
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-4.2.1.tgz

1.5.2 解压安装

1、解压

tar -zxvf mongodb-linux-x86_64-rhel70-4.2.1.tgz

2、创建目录

/usr/local/mongo

,并将解压完的

mongodb

目录移动到

/usr/local/mongo

mkdir -p /usr/local/mongo
mv mongodb-linux-x86_64-rhel70-4.2.1/* /usr/local/mongo/ 

3、切到

/usr/local/mongo

目录下,创建目录

mkdir -p data/db        #数据库目录
mkdir -p logs           #日志目录
mkdir -p conf           #配置文件目录
mkdir -p pids           #进程描述文件目录

创建好的目录如下:
在这里插入图片描述
4、在

conf

目录,增加配置文件

mongo.conf
vi /usr/local/mongo/conf/mongo.conf
#数据保存路径
dbpath=/usr/local/mongo/data/db/
#日志保存路径
logpath=/usr/local/mongo/logs/mongo.log
#进程描述文件
pidfilepath=/usr/local/mongo/pids/mongo.pid
#日志追加写入
logappend=true
bind_ip_all=true
#mongo默认端口
port=27017
#操作日志容量
oplogSize=10000
#开启子进程
fork=true

5、通过配置文件启动

mongo

服务端

/usr/local/mongo/bin/mongod -f /usr/local/mongo/conf/mongo.conf

启动成功如下:
在这里插入图片描述
6、启动

mongo

客户端

/usr/local/mongo/bin/mongo --host 127.0.0.1 --port 27017

启动成功如下:
在这里插入图片描述
至此安装完成~

1.6

MongoDB

基本操作及增删改查

1.6.1 基本操作

登陆数据库

mongo

查看数据库

show databases;

在这里插入图片描述
选择数据库

use

数据库名
在这里插入图片描述
如果切换到一个没有的数据库,例如

use admin2

,那么会隐式创建这个数据库。(后期当该数据库有数据时,系统自动创建)

use admin2

在这里插入图片描述
查看集合

show collections

在这里插入图片描述
创建集合

db.createCollection('集合名')

在这里插入图片描述
删除集合

`db.集合名.drop()`

在这里插入图片描述
删除数据库
通过

use

语法选择数据
通过

db.dropDataBase()

删除数据库
在这里插入图片描述

1.6.2 增删改查

1.6.2.1 增加

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

如果集合存在,那么直接插入数据。如果集合不存在,那么会隐式创建。

示例:在

test2

数据库的

c1

集合中插入数据(姓名叫

webopenfather

年龄

18

岁)

use test2 db.c1.insert({uname:"webopenfather",age:18})
  • 数据库和集合不存在都隐式创建
  • 对象的键统一不加引号(方便看),但是查看集合数据时系统会自动加
  • mongodb会给每条数据增加一个全球唯一的_id在这里插入图片描述- _id键的组成在这里插入图片描述- 自己增加_id 可以,只需要给插入的JSON数据增加_id键即可覆盖(但实战强烈不推荐)db.c1.insert({_id:1, uname:"webopenfather", age:18})

一次性插入多条数据
传递数据,数组中写一个个

JSON

数据即可

db.c1.insert([     {uname:"z3", age:3},     {uname:"z4", age:4},     {uname:"w5", age:5} ])

**快速插入

10

条数据**
由于

mongodb

底层使用

JS

引擎实现的,所以支持部分

js

语法。因此:可以写

for

循环

for (var i=1; i<=10; i++) {     db.c2.insert({uanme: "a"+i, age: i}) }

查询文档

db.集合名.find(条件[,查询的列])

条件写法查询所有的数据{}或者不写查询age=6的数据{age:6}既要age=6又要性别=男{age:6,sex:‘男’}查询的列(可选参数)写法查询全部列(字段)不写只显示age列(字段){age:1}除了age列(字段)都显示{age:0}
其他语法

db.集合名.find({
            键:{运算符:值}
            })

运算符作用$gt大于$gte大于等于$lt小于$lte小于等于$ne不等于$inin$ninnot in
实例练习
查询所有数据

db.c1.find()

在这里插入图片描述
系统的

_id

无论如何都会存在

1、查询

age

大于

5

的数据

db.c1.find({age:{$gt:5}})

在这里插入图片描述
2、查询年龄是

5

岁、

8

岁、

10

岁的数据

db.c2.find({age:{$in:[5,8,10]}})

在这里插入图片描述
3、只看年龄列,或者年龄以外的列
在这里插入图片描述

1.6.3 修改文档

db.集合名.update(条件,新数据[是否新增,是否修改多条,])
  • 新数据此数据需要使用修改器,如果不使用,那么会将新数据替换原来的数据。1db.集合名.update(条件,{修改器:{键:值}}[是否新增,是否修改多条,]) 修改器作用inc递增rename重命名列set修改列值unset删除列
  • 是否新增 指条件匹配不到数据则插入(true是插入,false否不插入默认)db.c3.update({uname:"zs30"},{$set:{age:30}},true)在这里插入图片描述
  • 是否修改多条 指将匹配成功的数据都修改(true是,false否默认)db.c3.update({uname:"zs2"},{$set:{age:30}},false,true)

实例练习
准备工作

use test2;
for(var i = 1; i<= 10; i++){
    db.c3.insert( {"uname":"zs"+i,"age":i} );
}

1、将

{uname:"zs1"}

改为

{uname:"zs2"}
db.c3.update({uname:"zs1"},{$set:{uname:"zs2"}})

在这里插入图片描述
2、给

{uname:"zs10"}

的年龄加

2

岁或减

2

db.c3.update({uname:"zs10"},{$inc:{age:2}})

在这里插入图片描述
递减只需要将

2

改为

-2

即可。

综合练习插入数据:

db.c4.insert( {uname:"神龙教主",age:888,who:"男",other:"非国人"})

;

1.6.4 删除文档

db.集合名.remove(条件[,是否删除一条])
  • 是否删除一条true:是(删除的数据为第一条)

在这里插入图片描述

false

:否

db.c3.remove({uname:"zs3"})

在这里插入图片描述

1.6.5 总结

高级开发攻城狮统称:所有数据库都需要增删改查

CURD

标识

MongoDB

删除语法:

remove

Create
db.集合名.insert(JSON数据)

Delete
db.集合名.remove(条件 [,是否删除一条true是false否默认])

也就是默认删除多条

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

升级语法db.集合名.update(条件,{修改器:{键:值}})

Read
db.集合名.find(条件 [,查询的列])

1.7

MongoDB

存储数据类型

MongoDB

中每条记录称作一个文档,这个文档和我们平时用的

JSON

有点像,但也不完全一样。

JSON

是一种轻量级的数据交换格式。简洁和清晰的层次结构使得

JSON

成为理想的数据交换语言,

JSON

易于阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率,但是

JSON

也有它的局限性,比如它只有

null

、布尔、数字、字符串、数组和对象这几种数据类型,没有日期类型,只有一种数字类型,无法区分浮点数和整数,也没法表示正则表达式或者函数。由于这些局限性,

BSON

闪亮登场啦,

BSON

是一种类

JSON

的二进制形式的存储格式,简称

Binary JSON

,它和

JSON

一样,支持内嵌的文档对象和数组对象,但是

BSON

JSON

没有的一些数据类型,如

Date

BinData

类型,

MongoDB

使用

BSON

做为文档数据存储和网络传输格式。

1.7.1 数字

shell

默认使用

64

位浮点型数值,如下:

db.sang_collec.insert({x:3.1415926})
db.sang_collec.insert({x:3})

对于整型值,我们可以使用

NumberInt

或者

NumberLong

表示,如下:

db.sang_collec.insert({x:NumberInt(10)})
db.sang_collec.insert({x:NumberLong(12)})

1.7.2 字符串

字符串也可以直接存储,如下:

db.sang_collec.insert({x:"hello MongoDB!"})

1.7.3 正则表达式

正则表达式主要用在查询里边,查询时我们可以使用正则表达式,语法和

JavaScript

中正则表达式的语法相同,比如查询所有

key

x

value

hello

开始的文档且不区分大小写:

db.sang_collec.find({x:/^(hello)(.[a-zA-Z0-9])+/i})

1.7.4 数组

数组一样也是被支持的,如下:

db.sang_collec.insert({x:[1,2,3,4,new Date()]})

数组中的数据类型可以是多种多样的。

1.7.5 日期

MongoDB

支持

Date

类型的数据,可以直接

new

一个

Date

对象,如下:

db.sang_collec.insert({x:new Date()})

1.7.6 内嵌文档

一个文档也可以作为另一个文档的

value

,这个其实很好理解,如下:

db.sang_collect.insert({name:"三国演义",author:{name:"罗贯中",age:99}});

书有一个属性是作者,作者又有

name

,年龄等属性。

1.8

MongoDB

中的索引

1.8.1 索引创建

默认情况下,集合中的

_id

字段就是索引,我们可以通过

getIndexes()

方法来查看一个集合中的索引:

db.sang_collect.getIndexes()

结果如下:

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "sang.sang_collect"
    }
]

我们看到这里只有一个索引,就是

_id

现在我的集合中有

10000

个文档,我想要查询

x

1

的文档,我的查询操作如下:

db.sang_collect.find({x:1})

这种查询默认情况下会做全表扫描,我们可以用上篇文章介绍的

explain()

来查看一下查询计划,如下:

db.sang_collect.find({x:1}).explain("executionStats")

结果如下:

{
    "queryPlanner" : {
    },
    "executionStats" : {
        "executionSuccess" : true,
        "nReturned" : 1,
        "executionTimeMillis" : 15,
        "totalKeysExamined" : 0,
        "totalDocsExamined" : 10000,
        "executionStages" : {
            "stage" : "COLLSCAN",
            "filter" : {
                "x" : {
                    "$eq" : 1.0
                }
            },
            "nReturned" : 1,
            "executionTimeMillisEstimate" : 29,
            "works" : 10002,
            "advanced" : 1,
            "needTime" : 10000,
            "needYield" : 0,
            "saveState" : 78,
            "restoreState" : 78,
            "isEOF" : 1,
            "invalidates" : 0,
            "direction" : "forward",
            "docsExamined" : 10000
        }
    },
    "serverInfo" : {
    },
    "ok" : 1.0
}

结果比较长,我摘取了关键的一部分。我们可以看到查询方式是全表扫描,一共扫描了

10000

个文档才查出来我要的结果。实际上我要的文档就排第二个,但是系统不知道这个集合中一共有多少个

x

1

的文档,所以会把全表扫描完,这种方式当然很低效,但是如果我加上

limit

,如下:

db.sang_collect.find({x:1}).limit(1)

此时再看查询计划发现只扫描了两个文档就有结果了,但是如果我要查询

x

9999

的记录,那还是得把全表扫描一遍,此时,我们就可以给该字段建立索引,索引建立方式如下:

db.sang_collect.ensureIndex({x:1})

1表示升序,-1表示降序。当我们给x字段建立索引之后,再根据x字段去查询,速度就非常快了,我们看下面这个查询操作的执行计划:

db.sang_collect.find({x:9999}).explain("executionStats")

这个查询计划过长我就不贴出来了,我们可以重点关注查询要耗费的时间大幅度下降。

此时调用

getIndexes()

方法可以看到我们刚刚创建的索引,如下:

[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_",
        "ns" : "sang.sang_collect"
    },
    {
        "v" : 2,
        "key" : {
            "x" : 1.0
        },
        "name" : "x_1",
        "ns" : "sang.sang_collect"
    }
]

我们看到每个索引都有一个名字,默认的索引名字为字段名_排序值,当然我们也可以在创建索引时自定义索引名字,如下:

db.sang_collect.ensureIndex({x:1},{name:"myfirstindex"})

此时创建好的索引如下:

{
    "v" : 2,
    "key" : {
        "x" : 1.0
    },
    "name" : "myfirstindex",
    "ns" : "sang.sang_collect"
}

当然索引在创建的过程中还有许多其他可选参数,如下:

db.sang_collect.ensureIndex({x:1},{name:"myfirstindex",dropDups:true,background:true,unique:true,sparse:true,v:1,weights:99999})

关于这里的参数,我说一下:

  1. name
    

    表示索引的名称

  2. dropDups
    

    表示创建唯一性索引时如果出现重复,则将重复的删除,只保留第一个

  3. background
    

    是否在后台创建索引,在后台创建索引不影响数据库当前的操作,默认为

    false
    
  4. unique
    

    是否创建唯一索引,默认

    false
    
  5. sparse
    

    对文档中不存在的字段是否不起用索引,默认

    false
    
  6. v
    

    表示索引的版本号,默认为

    2
    
  7. weights
    

    表示索引的权重

此时创建好的索引如下:

{
    "v" : 1,
    "unique" : true,
    "key" : {
        "x" : 1.0
    },
    "name" : "myfirstindex",
    "ns" : "sang.sang_collect",
    "background" : true,
    "sparse" : true,
    "weights" : 99999.0
}

1.8.2 查看索引

getIndexes()

可以用来查看索引,我们还可以通过

totalIndexSize()

来查看索引的大小,如下:

db.sang_collect.totalIndexSize()

1.8.3 删除索引

我们可以按名称删除索引,如下:

db.sang_collect.dropIndex("xIndex")

表示删除一个名为

xIndex

的索引,当然我们也可以删除所有索引,如下:

db.sang_collect.dropIndexes()

1.8.4 总结

索引是个好东西,可以有效的提高查询速度,但是索引会降低插入、更新和删除的速度,因为这些操作不仅要更新文档,还要更新索引,

MongoDB

限制每个集合上最多有

64

个索引,我们在创建索引时要仔细斟酌索引的字段。

1.9

Java

操作

MongoDB

1.9.1 方式一

方式一采用的原生

Java

操作

MongoDB

1.9.1.1 前期准备

首先我们需要驱动,

MongoDB

Java

驱动我们可以直接在

Maven

中央仓库去下载,也可以创建

Maven

工程添加如下依赖:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver</artifactId>
    <version>3.5.0</version>
</dependency>

建议通过

Maven

来添加依赖,如果自己下载jar,需要下载如下三个jar:

1.org.mongodb:bson:jar:3.5.0
2.org.mongodb:mongodb-driver-core:jar:3.5.0
3.org.mongodb:mongodb-driver:jar:3.5.0

另外,在使用

Java

操作

MongoDB

之前,记得启动

MongoDB

1.9.1.2 获取集合

所有准备工作完成之后,我们首先需要一个MongoClient,如下:

MongoClient client =newMongoClient("192.168.248.136",27017);

然后通过如下方式获取一个数据库,如果要获取的数据库本身就存在,直接获取到,不存在

MongoDB

会自动创建:

MongoDatabase sang = client.getDatabase("sang");

然后通过如下方式获取一个名为c1的集合,这个集合存在的话就直接获取到,不存在的话

MongoDB

会自动创建出来,如下:

MongoCollection<Document> c = sang.getCollection("c1");

有了集合之后,我们就可以向集合中插入数据了。

1、增加操作
和在

shell

中的操作一样,我们可以一条一条的添加数据,也可以批量添加,添加单条数据操作如下:

Document d1 =newDocument();
d1.append("name","三国演义").append("author","罗贯中");
c.insertOne(d1);

添加多条数据的操作如下:

List<Document> collections =newArrayList<Document>();Document d1 =newDocument();
d1.append("name","三国演义").append("author","罗贯中");
collections.add(d1);Document d2 =newDocument();
d2.append("name","红楼梦").append("author","曹雪芹");
collections.add(d2);
c.insertMany(collections);

当然也可以通过

Robo 3T

查看修改结果:

db.集合名.find()

在这里插入图片描述
2、修改操作
可以修改查到的第一条数据,操作如下:

c.updateOne(Filters.eq("author", "罗贯中"), new Document("$set", new Document("name", "三国演义123")));

上例中小伙伴们也看到了修改器要如何使用,不管是

inc

,用法都一致,我这里不再一个一个演示。也可以修改查到的所有数据,如下:

c.updateMany(Filters.eq("author", "罗贯中"), new Document("$set", new Document("name", "三国演义456")));

3、删除操作
可以删除查到的一条数据,如下:

c.deleteOne(Filters.eq("author", "罗贯中"));

也可以删除查到的所有数据:

c.deleteMany(Filters.eq("author", "罗贯中"));
Filters

里边还有其他的查询条件,都是见名知意,不赘述。

4、 查询操作
可以直接查询所有文档:

FindIterable<Document> documents = c.find();MongoCursor<Document> iterator = documents.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}

也可以按照条件查询:

FindIterable<Document> documents = c.find(Filters.eq("author","罗贯中"));MongoCursor<Document> iterator = documents.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}

其他的方法基本都是见名知意,这里不再赘述。

5、验证问题
上面我们演示的获取一个集合是不需要登录

MongoDB

数据库的,如果需要登录,我们获取集合的方式改为下面这种:

ServerAddress serverAddress =newServerAddress("192.168.248.128",27017);List<MongoCredential> credentialsList =newArrayList<MongoCredential>();MongoCredential mc =MongoCredential.createScramSha1Credential("readuser","sang","123".toCharArray());
credentialsList.add(mc);MongoClient client =newMongoClient(serverAddress,credentialsList);MongoDatabase sang = client.getDatabase("sang");
c = sang.getCollection("c1");
MongoCredential

是一个凭证,第一个参数为用户名,第二个参数是要在哪个数据库中验证,第三个参数是密码的

char

数组,然后将登录地址封装成一个

ServerAddress

,最后将两个参数都传入

MongoClient

中实现登录功能。

6、其他配置
在连接数据库的时候也可以设置连接超时等信息,在

MongoClientOptions

中设置即可,设置方式如下:

ServerAddress serverAddress =newServerAddress("192.168.248.128",27017);List<MongoCredential> credentialsList =newArrayList<MongoCredential>();MongoCredential mc =MongoCredential.createScramSha1Credential("rwuser","sang","123".toCharArray());
credentialsList.add(mc);MongoClientOptions options =MongoClientOptions.builder()//设置连接超时时间为10s.connectTimeout(1000*10)//设置最长等待时间为10s.maxWaitTime(1000*10).build();MongoClient client =newMongoClient(serverAddress,credentialsList,options);MongoDatabase sang = client.getDatabase("sang");
c = sang.getCollection("c1");

1.9.2 方式二

主要讲解

SpringBoot

操作

MongoDB

实现增删改查的功能

1、

pom.xml

引入依赖

   <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>

2、创建

application.yml
spring:
  data:
    mongodb:
      host: 192.168.72.129
      database: studentdb

3、创建实体类
创建包

com.changan.mongodb

,包下建包

pojo

用于存放实体类,创建实体类

packagecom.changan.mongdb.pojo;importorg.springframework.data.annotation.Id;importorg.springframework.data.mongodb.core.mapping.Document;importjava.io.Serializable;@Document(collection ="student")publicclassStudentimplementsSerializable{@IdprivateLong id;privateString name;privateString sex;privateString age;privateString introduce;publicStringgetSex(){return sex;}publicvoidsetSex(String sex){this.sex = sex;}publicStringgetAge(){return age;}publicvoidsetAge(String age){this.age = age;}publicStringgetIntroduce(){return introduce;}publicvoidsetIntroduce(String introduce){this.introduce = introduce;}publicStringgetName(){return name;}publicvoidsetName(String name){this.name = name;}publicLonggetId(){return id;}publicvoidsetId(Long id){this.id = id;}}

4、创建数据访问接口

com.changan.mongodb

包下创建

dao

包,包下创建接口

packagecom.changan.mongdb.dao;importcom.changan.mongdb.pojo.Student;importjava.util.List;importjava.util.Map;publicinterfaceStudentDao{voidsave(Student student);voidupdate(Student student);List<Student>findAll();voiddelete(Integer id);}

5、创建业务逻辑类

com.changan.mongodb

包下创建

impl

包,包下创建类

packagecom.changan.mongdb.dao.impl;importcom.changan.mongdb.dao.StudentDao;importcom.changan.mongdb.pojo.Student;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.data.mongodb.core.MongoTemplate;importorg.springframework.data.mongodb.core.aggregation.Aggregation;importorg.springframework.data.mongodb.core.aggregation.LookupOperation;importorg.springframework.data.mongodb.core.query.Criteria;importorg.springframework.data.mongodb.core.query.Query;importorg.springframework.data.mongodb.core.query.Update;importorg.springframework.stereotype.Component;importjava.util.List;@ComponentpublicclassStudentDaoImplimplementsStudentDao{@AutowiredprivateMongoTemplate mongoTemplate;/**
     * 新增信息
     * @param student
     */@Overridepublicvoidsave(Student student){
        mongoTemplate.save(student);}/**
     * 修改信息
     * @param student
     */@Overridepublicvoidupdate(Student student){//修改的条件Query query =newQuery(Criteria.where("id").is(student.getId()));//修改的内容Update update =newUpdate();
        update.set("name",student.getName());

        mongoTemplate.updateFirst(query,update,Student.class);}/**
     * 查询所有信息
     * @return
     */@OverridepublicList<Student>findAll(){return mongoTemplate.findAll(Student.class);}/**
     * 根据id查询所有信息
     * @param id
     */@Overridepublicvoiddelete(Integer id){Student byId = mongoTemplate.findById(1,Student.class);
        mongoTemplate.remove(byId);}}

6、创建测试类

packagecom.changan.mongdb;importcom.changan.mongdb.dao.StudentDao;importcom.changan.mongdb.pojo.Student;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;importjava.util.List;importjava.util.Map;@RunWith(SpringRunner.class)@SpringBootTestpublicclassMongdbApplicationTests{@AutowiredprivateStudentDao studentDao;/**
     * 查询所有信息
     */@TestpublicvoidfindAll(){List<Student> all = studentDao.findAll();System.out.println(all.size());}/**
     * 新增信息
     */@Testpublicvoidsave(){Student student =newStudent();
        student.setId(6l);
        student.setName("宋人头");
        studentDao.save(student);}/**
     * 修改信息
     */@Testpublicvoidupdate(){Student student =newStudent();
        student.setId(2l);
        student.setName("吴很帅");
        studentDao.update(student);}/**
     * 删除信息
     */@Testpublicvoiddelete(){
        studentDao.delete(3);}}

1.10

MongoDB

之副本集配置

1.10.1

MongoDB

主从复制

主从复制是

MongoDB

最早使用的复制方式, 该复制方式易于配置,并且可以支持任意数量的从节点服务器,与使用单节点模式相比有如下优点:

在从服务器上存储数据副本,提高了数据的可用性, 并可以保证数据的安全性。

可配置读写分离,主节点负责写操作,从节点负责读操作,将读写压力分开,提高系统的稳定性。
在这里插入图片描述

MongoDB

的主从复制至少需要两个服务器或者节点。其中一个是主节点,负责处理客户端请求,其它的都是从节点,负责同步主节点的数据。

主节点记录在其上执行的所有写操作,从节点定期轮询主节点获取这些操作,然后再对自己的数据副本执行这些操作。由于和主节点执行了相同的操作,从节点就能保持与主节点的数据同步。

主节点的操作记录称为

oplog(operation log)

,它被存储在

MongoDB

local

数据库中。

oplog

中的每个文档都代表主节点上执行的一个操作。需要重点强调的是

oplog

只记录改变数据库状态的操作。比如,查询操作就不会被存储在

oplog

中。这是因为

oplog

只是作为从节点与主节点保持数据同步的机制。

然而,主从复制并非生产环境下推荐的复制方式,主要原因如下两点:

1、灾备都是完全人工的 如果主节点发生故障失败,管理员必须关闭一个从服务器,然后作为主节点重新启动它。然后应用程序必须重新配置连接新的主节点。
2、数据恢复困难 因为

oplog

只在主节点存在,故障失败需要在新的服务器上创建新的

oplog

,这意味着任意存在的节点需要重新从新的主节点同步

oplog

因此,在新版本的

MongoDB

中已经不再支持使用主从复制这种复制方式了,取而代之的是使用副本集复制方式。

1.10.2

MongoDB

副本集

MongoDB

副本集

(Replica Set)

其实就是具有自动故障恢复功能的主从集群,和主从复制最大的区别就是在副本集中没有固定的“主节点;整个副本集会选出一个节点作为“主节点”,当其挂掉后,再在剩下的从节点中选举一个节点成为新的“主节点”,在副本集中总有一个主节点

(primary)

和一个或多个备份节点

(secondary)

除了

primary

secondary

之外,副本集中的节点还可以是以下角色:
成为primary对客户端可见参与投票延迟同步复制数据Default√√√∕√Secondary-Only∕√√∕√Hidden∕∕√∕√Delayed∕√√√√Arbiters∕∕√∕∕Non-Voting√√∕∕√
官方推荐的副本集最小配置需要有三个节点:一个主节点接收和处理所有的写操作,两个备份节点通过复制主节点的操作来对主节点的数据进行同步备份。
在这里插入图片描述

1.10.2.1 配置副本集

1、环境准备
副本集各节点

IP

如下:

172.16.250.234
172.16.250.239
172.16.250.240

首先,先对三个

MongoDB

节点进行安装。

然后,依次修改各个节点的

mongodb.conf

配置文件,增加副本集相关配置,内容如下:

dbpath=/usr/local/mongodb-4.0.2/data
logpath=/usr/local/mongodb-4.0.2/log/mongodb.log
fork=true
logappend=true
bind_ip= # 此处填写服务器的IP
port=27017

# 设置副本集名称,在各个配置文件中,其值必须相同
replSet=rs0

配置完成之后,分别在三个节点上执行如下命令通过加载文件配置来启动

MongoDB

服务:

mongod -config /usr/local/mongodb-4.0.2/mongodb.conf
# 或者
mongod -f /usr/local/mongodb-4.0.2/mongodb.conf

至此,

3

MongoDB

实例都已经以副本集方式启动,但它们彼此之间现在还不会进行通信,仍需要进行一些配置。

2、副本集初始化
通过

Shell

连接到任意一个

MongoDB

实例,执行

rs.initiate()

方法对副本集进行初始化。

[root@hadoop34 mongodb-4.0.2]# mongo 172.16.250.234:27017
> conf=
    {
    "_id" : "rs0",
    "members" : [
        { "_id" : 0, "host" : "172.16.250.234:27017" },
        { "_id" : 1, "host" : "172.16.250.239:27017" },
        { "_id" : 2, "host" : "172.16.250.240:27017" }
        ]
    }
> rs.initiate(conf)
{
    "ok" : 1,
    "operationTime" : Timestamp(1542247326, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542247326, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
rs0:SECONDARY>

如果在执行

rs.initiate()

方法时不传入任何参数,

MongoDB

将以默认的配置文档对副本集进行初始化,后续可以再通过

rs.add()

方法来向副本集中添加成员。

3、副本集更新

# 向副本集中添加成员
rs.add("172.16.250.240:27017")
 
# 从副本集中删除成员
rs.remove("172.16.250.240:27017")
 
# 向副本集中添加仲裁
rs.addArb("172.16.250.240:27017")
 
# 向副本集中添加备份节点
rs.add({"_id":3,"host":"172.16.250.240:27017","priority":0,"hidden":true})

# 更改副本集配置
rs0:PRIMARY> var conf=rs.conf()
rs0:PRIMARY> conf.members[1].priority = 5
 
# PRIMARY节点上执行如下命令
rs0:PRIMARY> rs.reconfig(conf)
{
    "ok" : 1,
    "operationTime" : Timestamp(1542248518, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542248518, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
 
# SECONDARY节点上执行如下命令,需增加 force 参数
rs0:SECONDARY> rs.reconfig(conf,{force:true})
{
    "ok" : 1,
    "operationTime" : Timestamp(1542248726, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542248726, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}

例如,强制让一个节点成为

Primary

,可以将该节点的优先级设置成最高。

cfg = rs.conf()
cfg.members[0].priority = 5
cfg.members[1].priority = 1
cfg.members[2].priority = 1
rs.reconfig(cfg)

4、副本集监控

# 查看副本集的配置信息
rs0:PRIMARY> rs.conf()
{
    "_id" : "rs0",
    "version" : 104658,
    "protocolVersion" : NumberLong(1),
    "writeConcernMajorityJournalDefault" : true,
    "members" : [
    {
        "_id" : 0,
        "host" : "172.16.250.234:27017",
        "arbiterOnly" : false,
        "buildIndexes" : true,
        "hidden" : false,
        "priority" : 1,
        "tags" : {},
        "slaveDelay" : NumberLong(0),
        "votes" : 1
    },
    {
        "_id" : 1,
        "host" : "172.16.250.239:27017",
        "arbiterOnly" : false,
        "buildIndexes" : true,
        "hidden" : false,
        "priority" : 5,
        "tags" : {},
        "slaveDelay" : NumberLong(0),
        "votes" : 1
    },
    {
        "_id" : 2,
        "host" : "172.16.250.240:27017",
        "arbiterOnly" : false,
        "buildIndexes" : true,
        "hidden" : false,
        "priority" : 1,
        "tags" : {},
        "slaveDelay" : NumberLong(0),
        "votes" : 1
    }],
    "settings" : {
        "chainingAllowed" : true,
        "heartbeatIntervalMillis" : 2000,
        "heartbeatTimeoutSecs" : 10,
        "electionTimeoutMillis" : 10000,
        "catchUpTimeoutMillis" : -1,
        "catchUpTakeoverDelayMillis" : 30000,
        "getLastErrorModes" : {},
        "getLastErrorDefaults" : {
            "w" : 1,
            "wtimeout" : 0
        },
        "replicaSetId" : ObjectId("5becd39e360189766762e057")
    }
}
# 查看副本集运行状态
rs0:PRIMARY> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2018-11-15T02:46:15.138Z"),
    "myState" : 1,
    "term" : NumberLong(2),
    "syncingTo" : "",
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        }
    },
    "lastStableCheckpointTimestamp" : Timestamp(1542249916, 1),
    "members" : [
    {
        "_id" : 0,
        "name" : "172.16.250.234:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 2651,
        "optime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "optimeDurable" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "optimeDate" : ISODate("2018-11-15T02:46:06Z"),
        "optimeDurableDate" : ISODate("2018-11-15T02:46:06Z"),
        "lastHeartbeat" : ISODate("2018-11-15T02:46:13.520Z"),
        "lastHeartbeatRecv" : ISODate("2018-11-15T02:46:13.519Z"),
        "pingMs" : NumberLong(0),
        "lastHeartbeatMessage" : "",
        "syncingTo" : "172.16.250.239:27017",
        "syncSourceHost" : "172.16.250.239:27017",
        "syncSourceId" : 1,
        "infoMessage" : "",
        "configVersion" : 104658
        },
    {
        "_id" : 1,
        "name" : "172.16.250.239:27017",
        "health" : 1,
        "state" : 1,
        "stateStr" : "PRIMARY",
        "uptime" : 2799,
        "optime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "optimeDate" : ISODate("2018-11-15T02:46:06Z"),
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "infoMessage" : "",
        "electionTime" : Timestamp(1542248524, 1),
        "electionDate" : ISODate("2018-11-15T02:22:04Z"),
        "configVersion" : 104658,
        "self" : true,
        "lastHeartbeatMessage" : ""
    },
    {
        "_id" : 2,
        "name" : "172.16.250.240:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 1855,
        "optime" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "optimeDurable" : {
            "ts" : Timestamp(1542249966, 1),
            "t" : NumberLong(2)
        },
        "optimeDate" : ISODate("2018-11-15T02:46:06Z"),
        "optimeDurableDate" : ISODate("2018-11-15T02:46:06Z"),
        "lastHeartbeat" : ISODate("2018-11-15T02:46:13.520Z"),
        "lastHeartbeatRecv" : ISODate("2018-11-15T02:46:13.520Z"),
        "pingMs" : NumberLong(0),
        "lastHeartbeatMessage" : "",
        "syncingTo" : "172.16.250.239:27017",
        "syncSourceHost" : "172.16.250.239:27017",
        "syncSourceId" : 1,
        "infoMessage" : "",
        "configVersion" : 104658
    }],
    "ok" : 1,
    "operationTime" : Timestamp(1542249966, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542249966, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
# 查看备份节点的复制信息
rs0:PRIMARY> db.printSlaveReplicationInfo()
source: 172.16.250.234:27017
    syncedTo: Thu Nov 15 2018 11:08:36 GMT+0800 (CST)
    0 secs (0 hrs) behind the primary
source: 172.16.250.240:27017
    syncedTo: Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
    1542251316 secs (428403.14 hrs) behind the primary

1.10.2.2 副本集测试

Primary

上插入一万条客户数据:

rs0:PRIMARY> for(var i=0;i<10000;i++){db.customer.insert({"name":"user"+i})}
WriteResult({ "nInserted" : 1 })
rs0:PRIMARY> db.customer.count()
10000

Secondary

上查看客户数据是否已经同步:

rs0:SECONDARY> rs.slaveOk()
rs0:SECONDARY> db.customer.count()
10000

故障转移测试
执行如下命令关闭

Primary

节点,查看其他

2

个节点的情况:

mongod --shutdown --dbpath /usr/local/mongodb-4.0.2/data
# 查看Primary节点关闭之前的状态
rs0:PRIMARY> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2018-11-15T03:36:31.393Z"),
    "myState" : 1,
    "term" : NumberLong(4),
    "syncingTo" : "",
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        }
    },
    "lastStableCheckpointTimestamp" : Timestamp(1542252978, 1),
    "members" : [
    {
        "_id" : 0,
        "name" : "172.16.250.234:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 425,
        "optime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "optimeDurable" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2018-11-15T03:36:28Z"),
        "optimeDurableDate" : ISODate("2018-11-15T03:36:28Z"),
        "lastHeartbeat" : ISODate("2018-11-15T03:36:31.243Z"),
        "lastHeartbeatRecv" : ISODate("2018-11-15T03:36:30.233Z"),
        "pingMs" : NumberLong(0),
        "lastHeartbeatMessage" : "",
        "syncingTo" : "172.16.250.239:27017",
        "syncSourceHost" : "172.16.250.239:27017",
        "syncSourceId" : 1,
        "infoMessage" : "",
        "configVersion" : 104666
    },
    {
        "_id" : 1,
        "name" : "172.16.250.239:27017",
        "health" : 1,
        "state" : 1,
        "stateStr" : "PRIMARY",
        "uptime" : 428,
        "optime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2018-11-15T03:36:28Z"),
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "infoMessage" : "",
        "electionTime" : Timestamp(1542252577, 2),
        "electionDate" : ISODate("2018-11-15T03:29:37Z"),
        "configVersion" : 104666,
        "self" : true,
        "lastHeartbeatMessage" : ""
    },
    {
        "_id" : 2,
        "name" : "172.16.250.240:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 78,
        "optime" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "optimeDurable" : {
            "ts" : Timestamp(1542252988, 1),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2018-11-15T03:36:28Z"),
        "optimeDurableDate" : ISODate("2018-11-15T03:36:28Z"),
        "lastHeartbeat" : ISODate("2018-11-15T03:36:31.376Z"),
        "lastHeartbeatRecv" : ISODate("2018-11-15T03:36:29.597Z"),
        "pingMs" : NumberLong(0),
        "lastHeartbeatMessage" : "",
        "syncingTo" : "172.16.250.239:27017",
        "syncSourceHost" : "172.16.250.239:27017",
        "syncSourceId" : 1,
        "infoMessage" : "",
        "configVersion" : 104666
    }],
    "ok" : 1,
    "operationTime" : Timestamp(1542252988, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542252988, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}
# 在任意其他节点上查看Primary节点关闭之后的状态
> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2018-11-15T03:41:31.213Z"),
    "myState" : 1,
    "term" : NumberLong(5),
    "syncingTo" : "",
    "syncSourceHost" : "",
    "syncSourceId" : -1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1542253290, 1),
            "t" : NumberLong(5)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1542253290, 1),
            "t" : NumberLong(5)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1542253290, 1),
            "t" : NumberLong(5)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1542253290, 1),
            "t" : NumberLong(5)
        }
    },
    "lastStableCheckpointTimestamp" : Timestamp(1542253268, 1),
    "members" : [
    {
        "_id" : 0,
        "name" : "172.16.250.234:27017",
        "health" : 1,
        "state" : 1,
        "stateStr" : "PRIMARY",
        "uptime" : 6115,
        "optime" : {
            "ts" : Timestamp(1542253290, 1),
            "t" : NumberLong(5)
        },
        "optimeDate" : ISODate("2018-11-15T03:41:30Z"),
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "infoMessage" : "could not find member to sync from",
        "electionTime" : Timestamp(1542253288, 1),
        "electionDate" : ISODate("2018-11-15T03:41:28Z"),
        "configVersion" : 104666,
        "self" : true,
        "lastHeartbeatMessage" : ""
    },
    {
        "_id" : 1,
        "name" : "172.16.250.239:27017",
        "health" : 0,
        "state" : 8,
        "stateStr" : "(not reachable/healthy)",
        "uptime" : 0,
        "optime" : {
            "ts" : Timestamp(0, 0),
            "t" : NumberLong(-1)
        },
        "optimeDurable" : {
            "ts" : Timestamp(0, 0),
            "t" : NumberLong(-1)
        },
        "optimeDate" : ISODate("1970-01-01T00:00:00Z"),
        "optimeDurableDate" : ISODate("1970-01-01T00:00:00Z"),
        "lastHeartbeat" : ISODate("2018-11-15T03:41:30.593Z"),
        "lastHeartbeatRecv" : ISODate("2018-11-15T03:41:18.148Z"),
        "pingMs" : NumberLong(0),
        "lastHeartbeatMessage" : "Error connecting to 172.16.250.239:27017 :: caused by ::     Connection refused",
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "infoMessage" : "",
        "configVersion" : -1
    },
    {
        "_id" : 2,
        "name" : "172.16.250.240:27017",
        "health" : 1,
        "state" : 2,
        "stateStr" : "SECONDARY",
        "uptime" : 372,
        "optime" : {
            "ts" : Timestamp(1542253268, 1),
            "t" : NumberLong(4)
        },
        "optimeDurable" : {
            "ts" : Timestamp(1542253268, 1),
            "t" : NumberLong(4)
        },
        "optimeDate" : ISODate("2018-11-15T03:41:08Z"),
        "optimeDurableDate" : ISODate("2018-11-15T03:41:08Z"),
        "lastHeartbeat" : ISODate("2018-11-15T03:41:30.591Z"),
        "lastHeartbeatRecv" : ISODate("2018-11-15T03:41:31.106Z"),
        "pingMs" : NumberLong(0),
        "lastHeartbeatMessage" : "",
        "syncingTo" : "",
        "syncSourceHost" : "",
        "syncSourceId" : -1,
        "infoMessage" : "",
        "configVersion" : 104666
    }],
    "ok" : 1,
    "operationTime" : Timestamp(1542253290, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542253290, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}

再次启动

172.16.250.239:27017

节点,由于其选举优先级最高,自动被选举为

Primary

# 待172.16.250.239:27017 节点启动后再次查看副本集状态
> rs.status()
{
    "set" : "rs0",
    "date" : ISODate("2018-11-15T03:44:01.745Z"),
    "myState" : 2,
    "term" : NumberLong(6),
    "syncingTo" : "172.16.250.239:27017",
    "syncSourceHost" : "172.16.250.239:27017",
    "syncSourceId" : 1,
    "heartbeatIntervalMillis" : NumberLong(2000),
    "optimes" : {
        "lastCommittedOpTime" : {
            "ts" : Timestamp(1542253435, 1),
            "t" : NumberLong(6)
        },
        "readConcernMajorityOpTime" : {
            "ts" : Timestamp(1542253435, 1),
            "t" : NumberLong(6)
        },
        "appliedOpTime" : {
            "ts" : Timestamp(1542253435, 1),
            "t" : NumberLong(6)
        },
        "durableOpTime" : {
            "ts" : Timestamp(1542253435, 1),
            "t" : NumberLong(6)
        }
    },
    "lastStableCheckpointTimestamp" : Timestamp(1542253400, 1),
    "members" : [
        {
            "_id" : 0,
            "name" : "172.16.250.234:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 6265,
            "optime" : {
                "ts" : Timestamp(1542253435, 1),
                "t" : NumberLong(6)
            },
            "optimeDate" : ISODate("2018-11-15T03:43:55Z"),
            "syncingTo" : "172.16.250.239:27017",
            "syncSourceHost" : "172.16.250.239:27017",
            "syncSourceId" : 1,
            "infoMessage" : "",
            "configVersion" : 104666,
            "self" : true,
            "lastHeartbeatMessage" : ""
        },
        {
            "_id" : 1,
            "name" : "172.16.250.239:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 23,
            "optime" : {
                "ts" : Timestamp(1542253435, 1),
                "t" : NumberLong(6)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1542253435, 1),
                "t" : NumberLong(6)
            },
            "optimeDate" : ISODate("2018-11-15T03:43:55Z"),
            "optimeDurableDate" : ISODate("2018-11-15T03:43:55Z"),
            "lastHeartbeat" : ISODate("2018-11-15T03:44:01.228Z"),
            "lastHeartbeatRecv" : ISODate("2018-11-15T03:44:00.835Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "",
            "syncSourceHost" : "",
            "syncSourceId" : -1,
            "infoMessage" : "",
            "electionTime" : Timestamp(1542253424, 1),
            "electionDate" : ISODate("2018-11-15T03:43:44Z"),
            "configVersion" : 104666
        },
        {
            "_id" : 2,
            "name" : "172.16.250.240:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 522,
            "optime" : {
                "ts" : Timestamp(1542253435, 1),
                "t" : NumberLong(6)
            },
            "optimeDurable" : {
                "ts" : Timestamp(1542253435, 1),
                "t" : NumberLong(6)
            },
            "optimeDate" : ISODate("2018-11-15T03:43:55Z"),
            "optimeDurableDate" : ISODate("2018-11-15T03:43:55Z"),
            "lastHeartbeat" : ISODate("2018-11-15T03:44:01.166Z"),
            "lastHeartbeatRecv" : ISODate("2018-11-15T03:44:01.414Z"),
            "pingMs" : NumberLong(0),
            "lastHeartbeatMessage" : "",
            "syncingTo" : "172.16.250.239:27017",
            "syncSourceHost" : "172.16.250.239:27017",
            "syncSourceId" : 1,
            "infoMessage" : "",
            "configVersion" : 104666
        }
    ],
    "ok" : 1,
    "operationTime" : Timestamp(1542253435, 1),
    "$clusterTime" : {
        "clusterTime" : Timestamp(1542253435, 1),
        "signature" : {
            "hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
            "keyId" : NumberLong(0)
        }
    }
}

1.10.2.3 开启安全认证

创建用户
登录

PRIMARY

节点创建用户,在此我们对

test

库开启安全认证。

rs0:PRIMARY> show dbs
admin   0.000GB
config  0.000GB
local   0.002GB
test    0.000GB
rs0:PRIMARY> use admin
switched to db admin
rs0:PRIMARY> db.createUser({user:"root",pwd:"123456",roles:[{role:"userAdminAnyDatabase",db:"admin"}]})
Successfully added user: {
    "user" : "root",
    "roles" : [
        {
            "role" : "userAdminAnyDatabase",
            "db" : "admin"
        }
    ]
}
rs0:PRIMARY> use test
switched to db test
rs0:PRIMARY> db.createUser({user:"admin",pwd:"admin",roles:[{role:"readWrite",db:"test"}]})
Successfully added user: {
    "user" : "admin",
    "roles" : [
        {
            "role" : "readWrite",
            "db" : "test"
        }
    ]
}

**创建

keyFile

文件**
先停掉所有

SECONDARY

节点的

MongoDB

服务,然后再停掉

PRIMARY

节点的

MongoDB

服务,并在

PRIMARY

节点所在服务器上创建

keyFile

文件。

[root@hadoop39 mongodb-4.0.2]# openssl rand -base64 666 > /usr/local/mongodb-4.0.2/keyfile
[root@hadoop39 mongodb-4.0.2]# chmod 600 /usr/local/mongodb-4.0.2/keyfile

将生成的

keyFile

文件拷贝到其他节点服务器上,并修改文件的操作权限为

600

    chmod 600 /usr/local/mongodb-4.0.2/keyfile

更新启动配置文件
修改

PRIMARY

节点的

mongodb.conf

文件,增加如下内容:

# Add below Config
auth=true
oplogSize=100
keyFile=/usr/local/mongodb-4.0.2/keyfile

修改

SECONDARY

节点的

mongodb.conf

文件,增加如下内容:

# Add below Config
oplogSize=100
keyFile=/usr/local/mongodb-4.0.2/keyfile

启动副本集
先以

--auth

方式启动

PRIMARY

节点:

[root@hadoop39 mongodb-4.0.2]# mongod -f /usr/local/mongodb-4.0.2/mongodb.conf

再启动

SECONDARY

节点:

    mongod -f /usr/local/mongodb-4.0.2/mongodb.conf

登录测试

[root@hadoop39 mongodb-4.0.2]# mongo -uadmin -padmin 172.16.250.239:27017
MongoDB shell version v4.0.2
connecting to: mongodb://172.16.250.239:27017/test
MongoDB server version: 4.0.2
rs0:PRIMARY> show dbs;
test 0.000GB
admin

用户只能看到

test

库。

标签: MongoDB NoSQL bson

本文转载自: https://blog.csdn.net/weixin_42039228/article/details/123657641
版权归原作者 sunnyday0426 所有, 如有侵权,请联系我们删除。

“MongoDB详解,用心看这篇就够了【重点】”的评论:

还没有评论