概要:
mongoDB的聚合操作mongodb 集群:复制mongodb 集群:分片知识点:
pipeline 聚合mapRedurce 聚合在聚合中使用索引pipeline相关运算符:
$match :匹配过滤聚合的数据$project:返回需要聚合的字段$group:统计聚合数据示例:
# $match 与 $project使用 db.emp.aggregate( {$match:{"dep":{$eq:"客服部"}}}, {$project:{name:1,dep:1,salary:1}} ); # $group 与 $sum 使用 db.emp.aggregate( {$project:{dep:1,salary:1}}, {$group:{"_id":"$dep",total:{$sum:"$salary"}}} ); # 低于4000 忽略 db.emp.aggregate( {$match:{salary:{$gt:4000}}}, {$project:{dep:1,salary:1}}, {$group:{"_id":"$dep",total:{$sum:"$salary"}}} ); # 基于多个字段 进行组合group 部门+职位进行统计 db.emp.aggregate( {$project:{dep:1,job:1,salary:1}}, {$group:{"_id":{"dep":"$dep","job":"$job"},total:{$sum:"$salary"}}} );二次过滤
db.emp.aggregate( {$project:{dep:1,job:1,salary:1}}, {$group:{"_id":{"dep":"$dep","job":"$job"},total:{$sum:"$salary"}}}, {$match:{"$total":{$gt:10000}}} );mapRedurce 说明: 为什么需要 MapReduce? (1) 海量数据在单机上处理因为硬件资源限制,无法胜任 (2) 而一旦将单机版程序扩展到集群来分布式运行,将极大增加程序的复杂度和开发难度 (3) 引入 MapReduce 框架后,开发人员可以将绝大部分工作集中在业务逻辑的开发上,而将 分布式计算中的复杂性交由框架来处理
mongodb中mapRedurce的使用流程
创建Map函数,创建Redurce函数将map、Redurce 函数添加至集合中,并返回新的结果集查询新的结果集示例操作
// 创建map 对象 var map1=function (){ emit(this.job,1); } // 创建reduce 对象 var reduce1=function(job,count){ return Array.sum(count); } // 执行mapReduce 任务 并将结果放到新的集合 result 当中 db.emp.mapReduce(map1,reduce1,{out:"result"}) // 查询新的集合 db.result.find() # 使用复合对象作为key var map2=function (){ emit({"job":this.job,"dep":this.dep},1); } var reduce2=function(key,values){ return values.length; } db.emp.mapReduce(map2,reduce2,{out:"result2"}).find()mapRedurce的原理 在map函数中使用emit函数添加指定的 key 与Value ,相同的key 将会发给Redurce进行聚合操作,所以Redurce函数中第二个参数 就是 所有集的数组。return 的显示就是聚合要显示的值。
通过 M a t h 内 可 以 包 合 对 Math内 可以包合对 Math内可以包合对text 的运算 示例:
db.project.aggregate( {$match:{$text:{$search:"apache"}}}, {$project:{"name":1,"price":1}}, {$group:{_id:"$name",price:{$sum:"$price"}}} )关于索引 除了全文索引之外,还有单键索引。即整个字段的值作为索引。单键索引用值1和-1表示,分别代表正序和降序索引。
示例: de 创建单键索引
db.emp.createIndex({"dep":1})查看基于索引的执行计划
db.emp.find({"dep":"客服部"}).explain()除了单键索引外还可以创建联合索引如下:
db.emp.createIndex({"dep":1,"job":-1})查看 复合索引的执行计划
db.emp.find({"dep":"ddd"}).explain()查看索引在排序当中的使用
db.emp.find().sort({"job":-1,"dep":1}).explain()知识点:
复制集群的架构复制集群搭建复制集群的选举配置主节点配置
dbpath=/data/mongo/master port=27017 fork=true logpath=master.log replSet=tulingCluster从节点配置
dbpath=/data/mongo/slave port=27018 fork=true logpath=slave.log replSet=tulingCluster#子节点配置2
dbpath=/data/mongo/slave2 port=27019 fork=true logpath=slave2.log replSet=tulingCluster 分别启动三个节点 进入其中一个节点集群复制配置管理
#查看复制集群的帮助方法 rs.help()添加配置
// 声明配置变量 var cfg ={"_id":"tulingCluster", "members":[ {"_id":0,"host":"127.0.0.1:27017"}, {"_id":1,"host":"127.0.0.1:27018"} ] } // 初始化配置 rs.initiate(cfg) // 查看集群状态 rs.status()变更节点示例:
// 插入新的复制节点 rs.add("127.0.0.1:27019") // 删除slave 节点 rs.remove("127.0.0.1:27019") 演示复制状态 进入主节点客户端 插入数据 进入从节点查看数据 尝试在从节点下插入数据注:默认节点下从节点不能读取数据。调用 rs.slaveOk() 解决。
为了保证高可用,在集群当中如果主节点挂掉后,会自动 在从节点中选举一个 重新做为主节点。
演示节点的切换操作 kill 主节点 进入从节点查看集群状态 。rs.status()选举的原理: 在mongodb 中通过在 集群配置中的 rs.属性值大小来决定选举谁做为主节点,通时也可以设置arbiterOnly 为true 表示 做为裁判节点用于执行选举操作,该配置下的节点 永远不会被选举为主节点和从节点。
示例:
重新配置节点 var cfg ={"_id":"tulingCluster", "protocolVersion" : 1, "members":[ {"_id":0,"host":"127.0.0.1:27017","priority":10}, {"_id":1,"host":"127.0.0.1:27018","priority":2}, {"_id":2,"host":"127.0.0.1:27019","arbiterOnly":true} ] } // 重新装载配置,并重新生成集群节点。 rs.reconfig(cfg) //重新查看集群状态 rs.status()节点说明: PRIMARY 节点: 可以查询和新增数据 SECONDARY 节点:只能查询 不能新增 基于priority 权重可以被选为主节点 RBITER 节点: 不能查询数据 和新增数据 ,不能变成主节点
知识点:
分片的概念mongodb 中的分片架构分片示例随着数据的增长,单机实例的瓶颈是很明显的。可以通过复制的机制应对压力,但mongodb中单个集群的 节点数量限制到了12个以内,所以需要通过分片进一步横向扩展。此外分片也可节约磁盘的存储。
分片中的节点说明:
路由节点(mongos):用于分发用户的请求,起到反向代理的作用。配置节点(config):用于存储分片的元数据信息,路由节基于元数据信息 决定把请求发给哪个分片。(3.4版本之后,该节点,必须使用复制集。)分片节点(shard):用于实际存储的节点,其每个数据块默认为64M,满了之后就会产生新的数据库。配置 并启动config 节点集群
进入shell 并添加 config 集群配置:
var cfg ={"_id":"configCluster", "protocolVersion" : 1, "members":[ {"_id":0,"host":"127.0.0.1:37017"}, {"_id":1,"host":"127.0.0.1:37018"} ] } // 重新装载配置,并重新生成集群。 rs.initiate(cfg)配置 路由节点 mongos ==============
// 添加分片节点
sh.status() sh.addShard("127.0.0.1:47017"); sh.addShard("127.0.0.1:47018");为数据库开启分片功能
sh.enableSharding("tuling")为指定集合开启分片功能
sh.shardCollection("tuling.emp",{"_id":1})修改分片大小
use config db.settings.find() db.settings.save({_id:"chunksize",value:1})尝试插入1万条数据:
for(var i=1;i<=100000;i++){ db.emp.insert({"_id":i,"name":"copy"+i}); }// 创建管理员用户
use admin; db.createUser({"user":"admin","pwd":"123456","roles":["root"]}) #验证用户信息 db.auth("admin","123456") #查看用户信息 db.getUsers() # 修改密码 db.changeUserPassword("admin","123456")以auth 方式启动mongod,需要添加auth=true 参数 ,mongdb 的权限体系才会起作用:
#以auth 方向启动mongod (也可以在mongo.conf 中添加auth=true 参数) ./bin/mongod -f conf/mongo.conf --auth # 验证用户 use admin; db.auth("admin","123456")创建只读用户
db.createUser({"user":"dev","pwd":"123456","roles":["read"]})重新登陆 验证用户权限
use luban ; db.auth("dev","123456") 演示查看数据 演示插入数据