MongoDB的设计和应用
本篇内容简介:
一、MongoDB简介
1. MongoDB和MySQL 的名词映射
2. MySQL的数据迁移到MongoDB (通过CSV文件)
二、MongoDB的Golang类库使用
(demo+常用功能封装,详见下载:https://download.csdn.net/download/duringnone/12245262)
三、使用注意事项
四、设计模式+索引优化+MongoDB架构迭代
1. MongoDB的构建模式+ 部分实例(数据库设计规则参考)
2. 企业实例(构建模式 + 架构设计到优化方案)
3. 索引优化 + 架构思考【简介】
一、简介 (MongoDB介绍+使用可见前两篇博客)
1、MongoDB和Mysql 的名词映射
RDBMS(关键字/解释) | MongoDB(关键字/解释) |
---|---|
数据库(database) | 数据库(database) |
表格(table) | 集合(collection) |
行(row) | 文档(document) |
列(column) | 字段(field) |
表联合(table joins) | 嵌入文档() |
索引(index) | 索引(index) |
主键 | 主键(MongoDB提供了key为 _id) |
Mysqld(服务端入口文件) | mongod(服务端入口文件) |
2. MySQL的数据迁移到MongoDB (通过CSV文件)
1) 将数据导入mongodb
/usr/local/mongodb/bin/mongoimport --db 目标数据库 --collection 目标数据集合 --type csv --headerline --ignoreBlanks --file 数据源文件 # 将数据源文件(csv格式)导入到目标数据库的目标集合中
实例:
/usr/local/mongodb/bin/mongoimport --db db_isr --collection tb_isr_visitors --type csv --headerline --ignoreBlanks --file /root/csv/tb_isr_records_1.csv # 将csv文件导入mongodb的db_isr.db_isr_visitors集合中
二、MongoDB的Golang类库
1. 类库github地址:
https://github.com/mongodb/mongo-go-driver // mongodb官方提供的golang类库(截止20200311,暂不支持$lookup联表操作)
2. go get安装命令:
go get -u go.mongodb.org/mongo-driver # 使用go get 安装
3. go get gopkg.in/mgo.v2 // 安装mgo包,mgo是老版本的golang类库,官方已停止维护,但支持$lookup操作
4. 如若需要使用MongoDB-Golang类库的同学,可以去笔者的资源文件中下载,MongoDB-Golang,这个文件目录是笔者在Golang中使用MongoDB时,基于 mgo, mongo-go-dirver 这两个MongoDB常用golang类库的封装
1)MongoDB-Golang涉及的功能:
A) mgo,mongo-go-driver的连接池,增加,删除,修改,查看,多表关联查询,管道聚合操作,事务操作,原生mongo shells命令执行 等功能
B)上述所有功能均提供了详细的demo实例,并提供使用MongoDB从0-1的过程描述,并标注笔者的踩坑点和经验;下载后注意先看readme.txt
2)mgo和mongo-go-driver的区别:
A) 二者提供的功能上有交集,有互补:mongo-go-driver是MongoDB官方提供的Golang类库,持续更新中,但截止2020-02-29时,version=1.4+,仍不支持 $lookup操作(多表关联查询)和$graph操作(MongoDB提供的地理位置查询);而 mgo 官方已经停止更新,但提供 $lookup操作 【实测】
B) 二者性能不同:笔者使用体验下来,mongo-go-driver性能优于mgo性能,体现在维护golang和MongoDB的连接和连接设置上,具体的有兴趣可以看看二者源码
C) 二者使用习惯不用:mgo使用的连贯操作更多(类似PHP的ThinkPHP5,tp3等框架),而mongo-go-driver使用依赖注入更多一些(类似PHP的YII2,Laravel等框架)
3)使用本MongoDB-Golang 工具代码块 适应人群
A 首先本代码块是基于企业业务的封装,具有普遍使用性,涵盖了绝大部分应用场景
B) 适合MongoDB初学者:降低学习成本,底层实现对使用者透明,操作简单,提升开发效率
C) 适合从RDB(关系型数据库)刚转用MongoDB的使用者:此封装照顾了 MySQL等RDB使用者的用户习惯,返回的数据格式和ORM(关系映射数据格式)基本一致,
D) 照顾了 PHP 转 Golang的使用者,笔者以前也做过PHP,故使用过PHP的YII2,Laravel,ThinkPHP的开发者也能很清晰的看懂封装逻辑
E) 适合还未参加工作的同学,这些代码来自企业的基础功能包,是真实的工作代码
F) 本文件目录为功能代码块,可参考笔者的一篇MongoDB相关的博客使用,包含作者踩过的一些坑,可帮助初学使用者加深理解,内容涉及MongoDB相关(安装,常识,Mysql和MongoDB的基本对比,原生mongo shell命令...)
三、注意项
1. 聚合操作时$sum 操作作用同Mysql的count()和sum(),
db.tb_users.aggregate([{count:$sum:1}]) // select count(*) from tb_users
db.tb_users.aggregate([{count:$sum:"$age"}]) // select sum(age) from tb_users
***注意: mongodb的集合tb_users的字段age必须是数字类型,若是字符串类型,则无法使用sum()的功能
2. MongoDB对字段类型严格,若设置字段age为int,则db.tb_users.find({age:{$ge:"22"}); 无法获取查询结果,正确写法: db.tb_users.find({age:{$ge:22}})
3. 查询集合文档(对应Mysql数据表行记录)和聚合查询(类似Mysql的聚合函数操作)优化方案
1) 片键使用(查询是否命中片键,片键:mongo分片存储的规则,如hash)
2) 索引命中(match+project 都包含于 索引中,则从内存中读取,否则磁盘读取; 聚合操作中只有第一个match会用到索引; 通过project操作过滤掉不必要的字段,减少传输带宽过大造成的内存损耗)
4. MongoDB的集合(数据表)关系和设计原则参考
1->1: 内嵌
1->多:内嵌数组,或多 侧引用(引用另一个集合的_id等唯一键)
多->多: 跟实际情况而定
4. MongoDB的集合(数据表)中,单个文档(行记录)最大不超过16MB
5. 两个操作内存上限:
1) 单个文档存储最大不超过16MB,超过16MB会异常,可通过设置标记字段,标记当前文档为异常文档,详情参见(六-1-构建模式-异常模式)
2)MongoDB的内存操作最大不超过100MB,否则异常,但可通过设置allowDiskUse=true实现大于100MB的操作;缺点是allowDiskUse=true会将数据写入磁盘中,会降低响应速度; 例如:管道聚合操作时,使用allowDiskUse后比使用前,响应更慢
6. MongoDB的事务支持: MongoDB-4.0以前只支持单文档事务,Mongo-4.0开始支持副本集事务(跨文档事务),MongoDB-4.2开始支持副本集(跨文档事务),分片事务(跨分片事务)
7. remove() 方法 并不会真正释放空间。需要继续手动回收磁盘空间: 执行 db.repairDatabase(); 或 db.runCommand({ repairDatabase: 1 });
8. 删除集合文档时,错误写法:db.demo20191223.remove(); 正确写法:必须 db.demo20191223.remove({})
9. 多表关联查询:关键字$lookup,属于MongoDB的管道聚合操作,类似MySQL的聚合函数查询;
A)语法:
db.demoA.aggregate([$lookup:{
from:"tb_users", // 被关联的集合
localField:"a_uid", // demoA中的字段a_uid
foreignFeild:uid", // tb_users中的字段uid
as:"res" // 联表查询结果的别名
}]); // 类似SQL: SELECT * FROM demoA a LEFT JOIN tb_users tu ON tu.uid = a.a_uid;
B) 实例如: db.tb_flows.aggregate([
{$match:{app_id:"1008611",flow_add_date:2