一、MongoDB概述
1.MongoDB简介
MongoDB 是一个开源的、跨平台的、面向文档的、基于分布式文件存储的数据库系统,MongoDB 是由 C++ 语言开发,旨在为 Web 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下,通过添加更多的节点,可以保证服务器性能。
MongoDB 常常被归类为 NoSQL 数据库系统,也是当前 NoSQL 数据库中比较热门的一种。
2、MongoDB 特点
MongoDB 作为非关系性文档数据库有着以下几个主要特点:
- 高性能:MongoDB 提供了高性能的数据持久化方式,包括了对嵌入式数据模型的支持(减少了数据库系统上的 I/O 操作)。对更多的索引类型的支持(更快的查询),并且可以包含来自嵌入式文档和数组的键;
- 高可用:MongoDB 的复制工具(称为副本集)提供:自动故障转移、数据冗余。副本集是一组维护相同数据集合的 MongoDB 实例,提供了冗余和提高了数据可用性;
- 水平拓展:MongoDB 提供水平可伸缩性作为其核心功能的一部分:分片将数据分布在一个集群的机器上。从 3.4 开始,MongoDB 支持基于分片键创建数据区域。在平衡群集中,MongoDB 仅将区域覆盖的读写定向到区域内的那些分片;
- 丰富的查询语言:MongoDB 支持丰富的查询语言以支持读写操作(CRUD)以及:数据聚合、文本搜索和地理空间查询;
- 支持多种存储引擎:MongoDB支持多个存储引擎:WiredTiger 存储引擎(包括对静态加密的支持 )、内存存储引擎。 另外,MongoDB 提供可插拔的存储引擎 API,允许第三方为 MongoDB 开发存储引擎。
3、MongoDB 数据逻辑结构
MongoDB的一个实例,由多个数据库(Database)组成;一个数据库,由多个集合(Collection)组成;一个集合,又由多个文档(Document)组成!
在MongoDB数据库里是存在有数据库的概念,但是没有模式(所有的信息都是按照文档保存的),保存数据的结构就是JSON结构,只不过在进行一些数据处理的时候,才会使用MongoDB自己的一些操作符号。
cls命令可以清屏幕
二、数据库操作
新建数据库
语法:
use DATABASE_NAME
use:用于切换/创建数据库,若不存在则创建,否则切换到指定数据库。
DATABASE_NAME:数据库的名称。
如执行use test命令,创建数据库test。
查看数据库
查看全部数据库:
show dbs
查看当前数据库,需要先切换到指定数据库
db
删除数据库
语法:
db.dropDatabase()
如
三、集合操作
创建集合
语法:db.createCollection(name,
options)
方法创建集合。name
是要创建的集合的名称,options
是一个可选参数,用于指定集合的配置选项,
如:创建一个名为"myCollection"的普通集合
db.createCollection("myCollection")
删除集合
语法:
db.createCollection("myCollection")
如执行"db.myCollection.drop()"命令,删除集合myCollection
文档操作
单文档插入
db.COLLECTION_NAME.insert(document)
或者
db.COLLECTION_NAME.save(document)
多文本插入
db.COLLECTION_NAME.insertMany([document1,document2,.....])
insert()与save()方法的区别在于,若使用insert()方法插入文档时,集合中已存在该文档,则会报错。若使用save()方法插入文档时,集合中已存在该文档,则会覆盖。
如
插入如下学生信息:
{name:"张三", age:18, sex:"男",major:"大数据技术"},
{name:"李四", age:19, sex:"男",major:"大数据技术"},
{name:"王五", age:18, sex:"女",major:"人工智能"}
使用insert()方法
db.student.insert( {"name":"王五"," age":"18","sex":"女","major":"人工智能"})
使用insertMany([])方法
db.student.insertMany( [{"name":"张三", "age":"18", "sex":"男","major":"大数据技术"}, {"name":"李四"," age":"19","sex":"男","major":"大数据技术"}, {"name":"王五"," age":"18","sex":"女","major":"人工智能"}]))
执行“db.student.find()”命令,查看集合student中的文档内容
文档更新
更新单个文档
db.collection_name.updateOne()
db.collection_name.updateOne( { key1: value1 }, // 查询条件
{ $set: { key2: value2 } } // 更新操作);
/更新多个文档
db.collection_name.updateMany()
db.collection_name.updateMany( { key1: value1 }, // 查询条件
{ $set: { key2: value2 } } // 更新操作);
升级语法
db.集合名.update(条件,新数据) {修改器:{键:值}}
修改器 | 作用 |
$inc | 递增 |
$rename | 重命名列 |
$set | 修改列值 |
$unset | 删除列 |
案列说明
1.将{major:"人工智能"}修改为{major:"大数据技术"}
db.student.update({"major":"人工智能"},{$set:{"major":"大数据技术"}})
发现:默认不是修改,而是替换
解决:使用升级语法修改器
2.给{name:"张三"}的年龄加2岁或减2岁
db.student.update({"name":"张三"},{"$inc":{"age":2}})
db.student.update({"name":"张三"},{"$inc":{"age":-2}})
文档删除
删除单个文档
db.COLLECTION_NAME.remove()
删除多个文档
db.COLLECTION_NAME.remove({})
- db:当前数据库对象
- COLLECTION_NAME:当前集合对象
- remove():删除文档的条件,可选参数
删除集合student中键nickname为"Rose"的文档,具体操作命令如下
db.student.remove({"nickname":"Rose"})
查看集合中所有文档,验证文档是否删除成功,具体操作命令如下
db.student.find()
删除集合commet中全部文档,具体操作命令如下
db.student.remove({})
再次查看集合中所有文档,验证文档是否全部删除,具体操作命令如下
db.student.find()
文档简单查询
查询所有文档语法
db.COLLECTION_NAME.find()
查询所有文档,以易读的方式展示
db.COLLECTION_NAME.find().pretty()
- db:当前数据库对象
- COLLECTION_NAME:当前集合对象
- find():查询所有文档的方法
- pretty():格式化查询返回结果
按条件查询文档
基础语法:db.集合名.find(条件[,查询的列])
查询age为4,只显示它的姓名;
升级语法
db.集合名.find({键:值}) 注:值可以不直接写
{运算符:值}
db.集合名.find({
键:{运算符:值}
})
运算符 | 作用 |
$gt | 大于 |
$gte | 大于等于 |
$lt | 小于 |
$lte | 小于等于 |
$ne | 不等于 |
$in | in |
$nin | not in |
1.查询年龄大于5岁的数据
db.c1.find({age:{$gt:5}})
2.查询年龄是18岁、20岁、25岁的数据
db.c1.find({age:{$in:[18,20,25]}})
总结
db.集合名.insert(JSON数据)
db.集合名.remove([条件,是否删除一条true是false否默认])
也就是默认删除多条
db.集合名.update(条件, 新数据[,是否新增,是否修改多余条])
升级语法
db.集合名.update(条件,{修改器:{键:值}})
db.集合名.find(条件[,查询的列])
四、聚合操作
聚合操作是数据处理的一种方法,它涉及对一组数据执行计算,以返回总结性信息,如统计、分析或其他类型的汇总。聚合操作通常用于数据库和大数据环境中,以处理和转换大量数据。
- 单一作用聚合:提供了对常见聚合过程的简单访问,操作都从单个集合聚合文档。
- 聚合管道是一个数据聚合的框架,模型基于数据处理流水线的概念。文档进入多级管道,将 文档转换为聚合结果。
- MapReduce操作具有两个阶段:处理每个文档并向每个输入文档发射一个或多个对象的map阶段,以及reduce组合map操作的输出阶段
常见管道操作符如下表
常见管道操作符 | 相关说明 |
$group | 将集合中的文档进行分组,便于后续统计结果 |
$limit | 用于限制MongoDB聚合管道返回的文档数 |
$match | 用于过滤数据,只输出符合条件的文档 |
$sort | 将输入的文档先进行排序,再输出 |
$project | 用于修改输入文档的结构(增加、删除字段等)和名称 |
$skip | 在聚合管道中跳过指定数量的文档,并返回剩余的文档 |
五、副本集概述
副本集(replica set)是一组MongoDB实例保持其相同数据集的集群,由一个主(primary)服务器和多个副本(secondary)服务器构成。通过复制(replication)将数据的更新由主服务器推送到其他副本服务器上,在一定的延迟之后,达到每个MongoDB实例维护相同的数据集副本。
分片概述
分片(sharding)技术是开发人员用来提高数据存储和数据读写吞吐量常用的技术之一。简单来说。分片主要是将数据进行划分,然后将它们分别存放于不同机器上的过程。通过使用分片可以实现降低单个机器的压力和处理更大的数据负载功能。分片于副本集主要区别在于,分片是每个结点存储数据的不同片段,而副本集是每个结点存储数据的相同副本。
分片策略
1.范围分片
范围分片是一种基于分片键值范围的分片策略。在这种策略下,数据根据分片键的值被划分为多个连续的范围,每个范围对应一个片段。根据分片键上的范围将数据分配到分片。范围分片依赖于分片键具有良好的分布特征。范围分片的优点是可以实现数据的有序存储,从而提高范围查询的性能。然而,范围分片可能导致数据分布不均匀当分片键趋于单调或某些范围内的值过于集中时,可能导致某些分片上的数据或读写请求数相对较高,造成瓶颈,从而影响性能和可扩展性。
2.哈希分片
哈希分片是一种基于分片键值哈希的分片策略。将分片键进行哈希运算,然后根据哈希值对数据进行分配。这可以实现更均匀的数据分布和负载均衡,但牺牲了查询时基于范围的优化。在这种策略下,数据根据分片键的哈希值被划分为多个范围,每个范围对应一个片段。哈希分片的优点是可以实现数据的均匀分布,从而提高性能和可扩展性。然而,哈希分片可能导致数据的无序存储,从而降低范围查询的性能。
部署副本集
环境准备
首先配置副本路径,也就是配置三个实例,在配置之前先停止正在运行的mongo.exe,也就是我们的服务。
将之前配置好的MongoDB里的bin复制到Mongodb1,在MongoDB1中新建db文件夹和log文件夹存在对应的数据库数据以及日志数据。
启动三个实例
需要使用replSet命令,在每个bin目录下启动,注意路径不要写错
mongod -port 27017 -dbpath E:\XL\MongoDB\data -logpath E:\XL\MongoDB\log\mongo.log -logappend -replSet rs0
mongod -port 27018 -dbpath E:\XL\MongoDB1\data -logpath E:\XL\MongoDB1\log\mongo1.log -replSet rs0
mongod -port 27018 -dbpath E:\XL\MongoDB1\data -logpath E:\XL\MongoDB1\log\mongo1.log -replSet rs0
第一个案例
第二个案列
第三个案例
注意:
启动案例的方法和教程1中安装MongoDB的方法一致,都是一次性的服务,每次打开某个案列都需要启动服务才可以,如果要创建永久服务则需要安装服务。
配置集群
进入MongoDB,配置设置
1.先进入MongoDB,再切换到admin数据库
2.配置节点优先级
priority为节点优先级,数字越高,优先级越高
使用命令来查看复制集状态
rs.status()
最后出现PRIMARY表示状态是正确的,当前节点是主节点
我们现在已经完成复制集的搭建
验证MongoDB复制集
需要验证一下复制集的数据同步
在主节点27017上的test库collection集合c1中插入数据
use test
db.c1.insert({name:"xjt",age:1})
登录另一个节点27018验证是否同步
我们需要运行命令:副本集的从库持久设置
rs.slaveOk()
MongoDB复制集数据同步就完成了。
故障转移
比如关闭主节点案列(前面一直不关闭的窗口第一个)
登录27018端口,会发现,他变成了主节点
重新再启动27017节点时候,27018会转换成从节点
到这里副本部署就完成了
六、部署分片集群
环境准备
每个分片都应该安装MongoDB实例,和前面的主从复制类似,也需要将bin文件复制到每个分片中,并且创建data文件以及log文件存放数据库数据和日志数据
先创建两个shard
再shard1中再创建shard11和shard12,shard2同理
启动分片服务
启动分片服务1
进入要分片的数据库bin目录中,启动cmd
mongod --shardsvr --replSet shard1 -port 4006 -dbpath E:\XL\shard1\shard11\data -logpath E:\XL\shard1\shard11\log\shard11.log
--shardsvr为分片声明
不要关闭此窗口,最小化即可
再次进入要分片的数据库bin目录中,启动cmd
mongod --shardsvr --replSet shard1 -port 4007 -dbpath E:\XL\shard1\shard12\data -logpath E:\XL\shard1\shard12\log\shard12.log
启动分片服务2
进入要分片的数据库bin目录中,再次启动cmd
mongod --shardsvr --replSet shard2 -port 4008 --dbpath E:\XL\shard2\shard21\data -logpath E:\XL\shard2\shard21\log\shard21.log
进入要分片的数据库bin目录中,再再次启动cmd
mongod --shardsvr --replSet shard2 -port 4009 --dbpath E:\XL\shard2\shard22\data -logpath E:\XL\shard2\shard22\log\shard22.log
进入分片一初始化分片集
在shard1中的bin目录启动cmd
进入4006,配置数据信息
config={_id:"shard1",members:[
... {_id:0,host:"localhost:4006",priority:1},
... {_id:1,host:"localhost:4007",priority:2}
... ]}
初始化
进入分片二 初始化分片集
进入4008,配置数据
config={_id:"shard2",members:[
... {_id:0,host:"localhost:4008",priority:2},
... {_id:1,host:"localhost:4009",priority:1}
... ]}
配置启动Config Server
在MongoDB 3版本后config服务必须配置为从副本集,所以直接用前面设置好了的副本启动即可
同上,每个文件夹添加data和log,一共两个案例;两个cmd窗口
启动Config1:
进入要分片的数据库bin目录中
mongod --configsvr --replSet confset -port 4002 -dbpath E:\XL\config\config1\data -logpath E:\XL\config\config1\log\conf1.log
--configsvr 这里我们完全可以像启动普通MongoDB服务一样启动,不需要添加-shardsvr和configsvr参数。因为这两个参数的作用就是改变启动端口,所以自行指定了端口就可以
两个案列共两个窗口,一次性启动服务,不要关闭cmd窗口,最小化即可
启动Config2:
mongod --configsvr --replSet confset -port 4003 -dbpath E:\XL\config\config2\data -logpath E:\XL\config\config2\log\conf2.log
进入任何一个配置服务器的节点初始化配置服务的群集
重新打开一个cmd,在bin目录下
配置数据信息
config={_id:"confset",configsvr:true,members:[
... {_id:0,host:"localhost:4002"},
... {_id:1,host:"localhost:4003"}
... ]}
配置路由器服务器Route Process
可以创建专门的文件夹存放日志
在进入要分片的数据库bin目录中启动cmd
mongos --configdb confset/localhost:4002,localhost:4003 -logpath E:\XL\mongos\log\mongos.log -port 4000
mongos:mongos就是一个路由服务器,它会根据管理员设置的“片键”将数据分摊到自己管理的MongoDB集群,数据和片的对应关系以及相应的配置信息保存在“config服务器”上
配置分片sharding,添加分片索引
bin目录下使用MongoDB shell 登录到mongos ,添加shard节点
sh.addShard("shard1/localhost:4006,localhost:4007")
sh.addShard("shard2/localhost:4008,localhost:4009")
查看分片集
db.getSiblingDB("config").shards.finf()
mongodb分片测试
登录4000端口
指定要分片的数据库
sh.enableSharding("test")
指定数据库里需要分片的集合和片键,片键根据实际情况选择
sh.shardCollection("test.c2",{"id":"hashed"})//"hashed"表示哈希分片
sh.shardCollection("test.c2",{"id":1})//1表示范围分片
如果集合已经包含数据,则必须在分片集合之前创建一个支持分片键的索引,如果集合为空,则mongodb将创建索引
向test库里的c2集合插入10000条数据
for (var i=1;i<=10000;i++) db.c2.save({id:i,"test1":"testval"+i})
#查看c2信息
sh.status()
robo 3T查看分片集
robo 3T链接4000端口进行查看
也可以连接两个shard端口查看分片情况
最后
重新打开MongoDB服务,即可像原来一样使用,但数据存储方式和原来已经不一样了,变成了分布式的分片存储。
以上就是MongoDB的部署副本集和分片的基本操作了。