NoSQL05 - MongoDB副本集 MongoDB文档管理

一、MongoDB 副本集

1.1 副本集概述

1.1.1 副本集介绍

– mongodb 的复制至少需要两个节点。其中一个是主节点,负责处理客户端请求,其余的都是从节点,负责复制主节点上的数据。
– mongodb 各个节点常见的搭配方式为:一主一从、一主多从。
– 主节点记录在其上的所有操作 oplog ,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行这些操作,从而保证从节点的数据与主节点一致。

副本集就相当于 主从同步+高可用。

1.1.2 复制原理

• 副本集工作过程
– mongodb 各个节点常见的搭配方式为:一主一从、一主多从。
– 主节点记录所有操作到 oplog文件中 ,从节点定期轮询主节点获取这些操作,然后对自己的数据副本执行
这些操作,从而保证从节点的数据与主节点一致。

1.2.3 Replica Sets 复制集实现方式

Replica Sets 的结构类似一个集群,完全可以把它当成一个集群,因为它确实与集群实现的作用是一样的
如果其中一个节点出现故障,其他节点马上会将业务接管过来而无须停机操作

1.2.4 拓扑结构

1.2 配置 Replica Sets 副本集

1.2.1 启动 MongoDB 服务

1. 启动服务时,指定主机所在副本集名称
– 副本集成员间使用相同的副本集名称
– –replSet rs1 // 指定副本集名称
]# vim /usr/local/mongodb/etc/mongodb.conf  (51-53)
replSet=rs1

1.2.2 配置节点信息

• 在任意一台主机连接 mongod 服务,执行如下操作(51)
51 > config = {
_id:”rs1”,
members:[
{_id:0,host:”192.168.4.51:27051”},
{_id:1,host:”192.168.4.52:27052”},
{_id:2,host:”192.168.4.53:27053”}
]
}

1.2.3  初始化 Replica Sets 环境

51 >rs.initiate(config)    【只需要在一台机器上配置即可,先拿到副本信息的成为主库】

1.2.4 查看副本集信息

a. 查看状态信息
> rs.status()

b.查看是否是 master 库
> rs .isMaster()

1.2.5  验证副本集配置

a. 同步数据验证
– >db.getMongo( ).setSlaveOk( ) 允许从库查看数据

1.2.5 验证高可用

因为集群里面的会进行心跳检查。当一台机器宕掉的时候,一台从库发现主库已经挂掉了,他会通知其他从库说我们的主库已经挂掉了,需要重新选取主库了。这个时候从库会检查3个条件,只有这三个条件都满足了,才允许通知他的那台主机成为主库。

1.查看主库是否真的挂掉

2.查看通知他的那台数据库服务器上的数据是不是比自己的新

3.查看通知他的那台数据库服务器上的数据是不是比其他从库的数据新

[[email protected] ~]# mongod -f /usr/local/mongodb/etc/mongodb.conf –shutdown   //模拟主库挂掉

这个时候会自动竞选出新的主库。

[[email protected] ~]# mongo –host 192.168.4.53 –port 27053

rs1:PRIMARY> rs.isMaster()

    “primary” : “192.168.4.51:27051”,
    “me” : “192.168.4.51:27051”,

二、MongoDB 文档管理

2.1 插入文档

2.1.1 save( )

• 格式
– db. 集合名 .save({ key:“ 值”, key:” 值” })
• 注意
– 集合不存在时创建集合,后插入记录
– _id 字段值 已存在时 修改文档字段值
– _id 字段值 不已存在时 插入文档

rs1:PRIMARY> db.c2.find()
{ “_id” : ObjectId(“5b63073286e600078bb2da0f”), “name” : “lijun”, “likes” : [ “F” ] }

rs1:PRIMARY> db.c2.save({_id:ObjectId(“5b63073286e600078bb2da0f”),name:”lijun”,likes:[“B”]})
WriteResult({ “nMatched” : 1, “nUpserted” : 0, “nModified” : 1 })

rs1:PRIMARY> db.c2.find()
{ “_id” : ObjectId(“5b63073286e600078bb2da0f”), “name” : “lijun”, “likes” : [ “B” ] }

2.1.2 insert()

• 格式
– db. 集合名 .insert({key:“ 值”, key:” 值” })
• 注意
– 集合不存在时创建集合,后插入记录
– _id 字段值 已存在时放弃插入   【插入数组中已存在的数据会报错】
– _id 字段值 不已存在时 插入文档

rs1:PRIMARY> db.c2.find()
{ “_id” : ObjectId(“5b63073286e600078bb2da0f”), “name” : “lijun”, “likes” : [ “B” ] }

rs1:PRIMARY> db.c2.insert({_id:ObjectId(“5b63073286e600078bb2da0f”),sex:”girl”})    //报错, duplicate key error collection。不允许在重复的_id文档插入数据

2.1.3 insertMany()

db.c1.insertMany(
[
{name:”xiaojiu“,age:19} ,
{name:”laoshi“,email:”[email protected]”}
]
)        //插入多条记录

2.2 查询文档

2.2.1 查询语法

• 显示所有行,默认一次只输出 20 行 输入 it 显示后续的
> db. 集合名 .find()

rs1:PRIMARY> db.user.find()

• 显示第 1 行
> db. 集合名 .findOne()

rs1:PRIMARY> db.user.findOne()

• 指定查询条件并指定显示的字段
> db. 集合名 .find ( { 条件 },{ 定义显示的字段 } )   //第一个大括号里面写条件,第二个大括号里面写显示字段
> db.user.find({},{_id:0,name:1,shell:1})        // 0不显示  1 显示


2.2.2 行数显示限制

• limit( 数字 )     // 显示前几行
> db. 集合名 .find().limit(3)

• skip( 数字 )    // 跳过前几行
– > db. 集合名 .find().skip(2)

• sort( 字段名 )     // 排序
– > db. 集合名 .find().sort(age:1|-1) 1 升序 -1 降序
– > db.user.find({shell:”/sbin/nologin”},{_id:0,name:1,uid:1,shell:1}).skip(2).limit(2)    

2.2.3 查询条件

a.简单条件
– db. 集合名 .find({key:” 值” })
– db. 集合名 .find({key:” 值”, keyname:” 值” })
– db.user.find({shell:”/bin/bash”})
– db.user.find({shell:”/bin/bash”,name:”root”})   //逻辑与的关系

b.范围比较
in 在…里 > db.user.find({uid:{ in:[1,6,9]}})

n i n > d b . u s e r . f i n d ( u i d : $ n i n : [ 1 , 6 , 9 ] ) or 或
> db.user.find({$or: [{name:”root”},{uid:1} ]})
c. 正则匹配
> db.user.find({name: /^a/ })

d. 数值比较
lt       lte       gt       gte        $ne
<         <=         >         >=         !=

> db.user.find( { uid: { g t e : 10 , lte:40} } , {_id:0,name:1,uid:1})
– db.user.find({uid:{$lte:5,}})


e. 匹配 null , 也可以匹配没有的字段
> db.user.save({name:null,uid:null})

> db.user.find({name:null})
{ “_id” : ObjectId(“5afd0ddbd42772e7e458fc75”), “name” : null, “uid” : null }

2.3 更新文档

2.3.1 单文档更新

• 语法格式
> db. 集合名 .update({ 条件 },{ 修改的字段 } )
注意:把文件的其他字段都删除了,只留下了 password 字段, 且只修改与条件匹配的第 1 行 !!!

s e t / unset
s e t , d b . u s e r . u p d a t e ( , set: { 修改的字段 })
– db.user3.update({name:”bin”},{$set:{password:”A”}}

$unset 删除与条件匹配文档的字段
– db. 集合名 .update({ 条件 },{$unset:{key:values}})
– db.user3.updat

2.3.2 多文档更新

• 语法格式:默认只更新与条件匹配的第 1 行
– > db.user.update({ 条件 },{$set:{ 修改的字段 }} ,false,true )

> db.user.update({name:“bin”},{ set:{password:“abc12123”}} , false,true) &nbsp; //添加false,true就会更新匹配条件的所有文档,加 set就会设置改变指定的字段,而不会把其他的字段删除。


2.3.3 自加自减

inc 条件匹配时,字段值自加或自减 > Db. 集合名 .update({ 条件 },{ inc:{ 字段名 : 数字 }})        //正整数自加 负整数自减!!!!

> db.user.update({name:”bin”},{$inc:{uid:2}})             //字段值自加 2

> db.user.update({name:“bin”},{$inc:{uid:-1}})             //字段自减 1

2.3.4 向数组添加元素和删除元素

a. 向数组添加元素

> push 向数组中添加新元素 > db. 集合名 .update({ 条件 },{ push:{ 数组名 :“ 值” }})

> db.user.insert({name:”bob”,likes:[“a”,”b”,”c”,”d”,”e”,”f”]})

> db.user.update({name:“bob”},{$push:{likes:“w”}})

$addToSet 避免重复添加

> db. 集合名 .update({ 条件 },{ addToSet:{ 数组名 :”值” }})  > db.user.update({name:”bob”},{ addToSet:{likes:“f”}})

db.user.update({name:”bob”},{$addToSet:{likes:“g”}})

b. 向数组删除元素

pop 从数组头部删除一个元素 db. 集合名 .update({ 条件 },{ pop:{ 数组名 : 数字 }})
db.user.update({name:”bob”},{$pop:{likes:1}})              1 删除数组尾部元素

db.user.update({name:”bob”},{$pop:{likes:-1}})             -1 删除数组头部元素

pull 删除数组指定元素 – db. 集合名 .update({ 条件 },{ pull:{ 数组名 : 值 }})
– db.user.update({name:”bob”},{$pull:{likes:”b”}})

2.4 删除文档

d r o p / remove
• $drop 删除集合的同时删除索引
> db. 集合名 .drop( )
> db.user.drop( )

• remove() 删除文档时不删除索引
> db. 集合名 .remove({})              // 删除所有文档
> db. 集合名 .remove({ 条件 })     // 删除与条件匹配的文档

> db.user.remove({uid:{$lte:10}}) > db.user.remove({})