# MongoDB 相关概念
# 业务应用场景
# 解决三高需求
- High performance - 对数据库高并发读写的需求
- Huge Storage - 对海量数据的高效率存储和访问的需求
- High Scalability && High Availability- 对数据库的高可扩展性和高可用性的需求
# MongoDB 简介
MongoDB 是一个开源、高性能、无模式的文档型数据库,当初的设计就是用于简化开发和方便扩展,是 NoSQL 数据库产品中的一种。是最像关系型数据库(MySQL)的非关系型数据库
它支持的数据结构非常松散,是一种类似于 JSON 的 格式叫 BSON,所以它既可以存储比较复杂的数据类型,又相当的灵活
MongoDB 中的记录是一个文档,它是一个由字段和值对(fifield:value)组成的数据结构。MongoDB 文档类似于 JSON 对象,即一个文档认为就是一个对象。字段的数据类型是字符型,它的值除了使用基本的一些类型外,还可以包括其他文档、普通数组和文档数组
# 体系结构
# MySQL 和 MongoDB 对比
![image-20230714104932006]()
# 文字转述
SQL 术语 |
MongoDB 术语 |
解释 / 说明 |
database |
database |
数据库 |
table |
collection |
数据库表 / 集合 |
row |
document |
数据记录行 / 文档 |
column |
field |
数据字段 / 域 |
index |
index |
索引 |
table joins |
|
表连接,MongoDB 不支持 |
|
嵌入文档 |
MongoDB 通过嵌入式文档来替代多表连接 |
primary key |
primary key |
逐渐 MongoDB 自动将_id 字段设置为主键 |
# 数据类型
# 介绍
MongoDB 的最小存储单位就是文档 (document) 对象。文档 (document) 对象对应于关系型数据库的行。数据在 MongoDB 中以 BSON(Binary-JSON)文档的格式存储在磁盘上
BSON(Binary Serialized Document Format)是一种类 json 的一种二进制形式的存储格式,简称 Binary JSON。BSON 和 JSON 一样,支持内嵌的文档对象和数组对象,但是 BSON 有 JSON 没有的一些数据类型,如 Date 和 BinData 类型。
BSON 采用了类似于 C 语言结构体的名称、对表示方法,支持内嵌的文档对象和数组对象,具有轻量性、可遍历性、高效性的三个特点,可以有效描述非结构化数据和结构化数据。这种格式的优点是灵活性高,但它的缺点是空间利用率不是很理想。
Bson 中,除了基本的 JSON 类型:string,integer,boolean,double,null,array 和 object,mongo 还使用了特殊的数据类型。这些类型包括 date,object id,binary data,regular expression 和 code。每一个驱动都以特定语言的方式实现了这些类型,查看你的驱动的文档来获取详细信息。
# BSON 数据类型分类
数据类型 |
描述 |
举例 |
字符串 |
UTF-8 字符串都可表示为字符串类型的数据 |
|
对象 id |
对象 id 是文档的 12 字节的唯一 ID |
|
布尔值 |
真或者假:true 或者 false |
|
数组 |
值的集合或者列表可以表示成数组 |
|
32 位整数 |
类型不可用 JavaScript 仅支持 64 位浮点数,所以 32 位整数会被自动转换 |
shell 是不支持该类型的,shell 中默认会转换成 64 位浮点数 |
64 位整数 |
不支持这个类型。shell 会使用一个特殊的内嵌文档来显示 64 位整数 |
shell 是不支持该类型的,shell 中默认会转换成 64 位浮点数 |
64 位浮点数 |
shell 中的数字就是这一种类型 |
|
null |
表示空值或者未定义的对象 |
|
undefined |
文档中也可以使用未定义类型 |
|
符号 |
shell 不支持,shell 会将数据库中的符号类型的数据自动转换成字符串 |
|
正则表达式 |
文档中可以包含正则表达式,采用 JavaScript 的正则表达式语法 |
|
代码 |
文档中还可以包含 JavaScript 代码 |
{"x" : function() { /* …… */ }} |
二进制数据 |
二进制数据可以由任意字节的串组成,不过 shell 中无法使用 |
|
最大值 / 最小值 |
BSON 包括一个特殊类型,表示可能的最大值。shell 中没有这个 |
|
# MongoDB 特点
# 高性能
- 对嵌入式数据模型的支持减少了数据库系统上的 I/O 活动
- 索引支持更快的查询,并且可以包含来自嵌入式文档和数组的键。(文本索引解决搜索的需求、TTL 索引解决历史数据自动过期的需求、地理位置索引可用于构建各种 O2O 应用)
- mmapv1、wiredtiger、mongorocks(rocksdb)、in-memory 等多引擎支持满足各种场景需求
- Gridfs 解决文件存储的需求
# 高可用性
- MongoDB 的复制工具称为副本集(replica set),它可提供自动故障转移和数据冗余
# 高扩展性
- MongoDB 提供了水平可扩展性作为其核心功能的一部分
- 分片将数据分布在一组集群的机器上。(海量数据存储,服务能力水平扩展)
- 从 3.4 开始,MongoDB 支持基于片键创建数据区域。在一个平衡的集群中,MongoDB 将一个区域所覆盖的读写只定向到该区域内的那些片
# 丰富的查询支持
- MongoDB 支持丰富的查询语言,支持读和写操作 (CRUD),比如数据聚合、文本搜索和地理空间查询等
# 其它
# 单机部署
# Windows 系统中安装启动
# 直接启动
| mongod --dbpath=..\data\db |
# 配置文件启动
# 创建配置文件
| systemLog: |
| |
| |
| destination: file |
| |
| path: "/mongodb/single/log/mongod.log" |
| |
| logAppend: true |
| storage: |
| |
| |
| dbPath: "/mongodb/single/data/db" |
| journal: |
| |
| enabled: true |
| processManagement: |
| |
| fork: true |
| net: |
| |
| bindIp: localhost,192.168.0.2 |
| |
| |
| port: 27017 |
# 启动
| mongod --config D:/mongodb/mongod.conf |
| mongos -f D:/mongodb/mongos.conf |
# Shell 连接命令
| mongo --host=127.0.0.1 --port=27017 |
# Linux 系统中安装启动
# 创建配置文件
| |
| mkdir -p /mongodb/single/data/db |
| |
| mkdir -p /mongodb/single/log |
| vi /mongodb/single/mongod.conf |
| systemLog: |
| |
| |
| destination: file |
| |
| path: "/mongodb/single/log/mongod.log" |
| |
| logAppend: true |
| storage: |
| |
| |
| dbPath: "/mongodb/single/data/db" |
| journal: |
| |
| enabled: true |
| processManagement: |
| |
| fork: true |
| net: |
| |
| bindIp: localhost,192.168.0.2 |
| |
| |
| port: 27017 |
# 启动
| /usr/local/mongodb/bin/mongod -f /mongodb/single/mongod.conf |
# 基本常用命令
# 数据库操作
# 选择和创建数据库
# 查看数据库
# 数据库的删除
# 集合操作
# 集合的显式创建
| db.createCollection(name) |
# 查看当前库中的表
# 集合的隐式创建
当向一个集合中插入一个文档的时,集合不存在,则会自动创建集合
# 集合的删除
- 返回值:删除成功返回 true,否则返回 false
# 文档操作
# 文档的插入
# 单个文档插入
| db.collection.insert( |
| <document or array of document>, |
| { |
| writeConern: <document>, |
| ordered: <boolean> |
| } |
| ) |
# 参数
Parameter |
Type |
Description |
document |
document or array |
要插入到集合中的文档或文档数组 |
writeConcern |
document |
|
ordered |
boolean |
可选。如果为真,则按顺序插入数组中的文档,如果其中一个文档出现错误,MongoDB 将返回而不处理数组中的其余文档。如果为假,则执行无序插入,如果其中一个文档出现错误,则继续处理数组中的主文档。在版本 2.6 + 中默认为 true |
# 批量插入
| db.collection.insertMany( |
| [ <document 1>, <document 2>, ... ], |
| { |
| writeConcern: <document>, |
| ordered: <boolean> |
| } |
| ) |
# 参数
Paramter |
Type |
Description |
document |
document |
要插入到集合中的文档或数据 |
witeConcern |
document |
|
ordered |
boolean |
可选,一个布尔值,指定 Mongod 实例应执行有序插入还是无序插入 |
# 示例
| db.comment.insertMany([ |
| {"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"}, |
| {"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"}, |
| {"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"}, |
| {"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"}, |
| {"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"} |
| ]); |
# try-catch
| try { |
| db.comment.insertMany([ |
| {"_id":"1","articleid":"100001","content":"我们不应该把清晨浪费在手机上,健康很重要,一杯温水幸福你我他。","userid":"1002","nickname":"相忘于江湖","createdatetime":new Date("2019-08-05T22:08:15.522Z"),"likenum":NumberInt(1000),"state":"1"}, |
| {"_id":"2","articleid":"100001","content":"我夏天空腹喝凉开水,冬天喝温开水","userid":"1005","nickname":"伊人憔悴","createdatetime":new Date("2019-08-05T23:58:51.485Z"),"likenum":NumberInt(888),"state":"1"}, |
| {"_id":"3","articleid":"100001","content":"我一直喝凉开水,冬天夏天都喝。","userid":"1004","nickname":"杰克船长","createdatetime":new Date("2019-08-06T01:05:06.321Z"),"likenum":NumberInt(666),"state":"1"}, |
| {"_id":"4","articleid":"100001","content":"专家说不能空腹吃饭,影响健康。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T08:18:35.288Z"),"likenum":NumberInt(2000),"state":"1"}, |
| {"_id":"5","articleid":"100001","content":"研究表明,刚烧开的水千万不能喝,因为烫嘴。","userid":"1003","nickname":"凯撒","createdatetime":new Date("2019-08-06T11:01:02.521Z"),"likenum":NumberInt(3000),"state":"1"} |
| ]); |
| } catch (e) { |
| print (e); |
| } |
# 文档的查询
# 语法
| db.collection.find(<query>, [projection]) |
# 参数
Parameter |
Type |
Description |
query |
document |
可选,使用查询运算符指定选择筛选器,若要返回集合中的文档,可以传递空文档 ({}) |
projection |
document |
可选,指定要在与查询筛选器匹配的文档中返回的字段,若要返回匹配文档中的所有字段,请省略此参数 |
# 查询所有
# 投影查询
| db.comment.find({userid: "1003"},{userid: 1, nickname: 1}) |
# 文档更新
# 更新
| db.collection.update(query, update, option) |
# 覆盖修改
| db.comment.update({_id:"1"},{likenum:NumberInt(1001)}) |
# 局部修改
| db.comment.update({_id: "2"}, {$set:{likenum:NumberInt(889)}}) |
# 批量修改
| db.comment.update({userid:"1003"},{$set:{nickname: "凯撒"}}) |
# 删除文档
# 文档的分页查询
# 统计查询
# 语法
| db.collection.count(query, options) |
# 参数
Parameter |
Type |
Description |
query |
document |
查询选择条件 |
options |
document |
可选,用于修改计数的额外选项 |
# 分页列表查询
# 语法
| db.comment.find().limit(3) |
| db.comment.find().skip(3) |
# 排序查询
# 语法
| db.comment.find().sort({userid:-1,likenum:-1}) |
# 文档的更多查询
# 正则的复杂条件查询
# 语法
| db.comment.find({content: /~~/}) |
# 比较查询
# 语法
| db.comment.find({likenum:{$gt:NumberInt(700)}}) |
# 包含查询
# 语法
| db.comment.find({userid:{$in:["1003","1004"]}}) |
# 条件连接查询
# 语法
| db.comment.find({$and:[{likenum:{$gt:NumberInt(700)}},{likenum:{$lt:NumberInt(2000)}}]}) |
# 索引
# 概述
索引是特殊的数据结构,它以易于遍历的形式存储集合数据集的一小部分。索引存储特定字段或一组字段的值,按字段值排序。索引项的排序支持有效的相等匹配和基于范围的查询操作。此外,MongoDB 还可以使用索引中的排序返回排序结果
# 索引类型
# 单字段索引
MongoDB 支持在文档的单个字段上创建用户定义的升序 / 降序索引,称为单字段索引(Single Field Index)
对于单个字段索引和排序操作,索引键的排序顺序(即升序或降序)并不重要,因为 MongoDB 可以在任何方向上遍历索引
# 复合索引
MongoDB 还支持多个字段的用户定义索引,即复合索引(Compound Index)
复合索引中列出的字段顺序具有重要意义。例如,如果复合索引由 {userid: 1, score: -1} 组成,则索引首先按 userid 正序排序,然后在每个 userid 的值内,再在按 score 倒序排序
![image-20230714145824037]()
# 其它索引
# 地理空间索引(Geospatial Index)
为了支持对地理空间坐标数据的有效查询,MongoDB 提供了两种特殊的索引:返回结果时使用平面几何的二维索引和返回结果时使用球面几何的二维球面索引
# 文本索引(Text Indexes)
MongoDB 提供了一种文本索引类型,支持在集合中搜索字符串内容。这些文本索引不存储特定于语言的停止词(例如 “the”、“a”、“or”),而将集合中的词作为词干,只存储根词
# 哈希索引(Hashed Indexes)
为了支持基于散列的分片,MongoDB 提供了散列索引类型,它对字段值的散列进行索引。这些索引在其范围内的值分布更加随机,但只支持相等匹配,不支持基于范围的查询
# 索引的管理操作
# 索引的查看
| db.collection.getIndexes() |
# 索引的创建
| db.collection.createIndex(keys, options) |
# 索引的移除
| db.comment.dropIndex(index) |
# 索引的使用
# 执行计划
分析查询性能(Analyze Query Performance)通常使用执行计划(解释计划、Explain Plan)来查看查询的情况,如查询耗费的时间、是否基于索引查询等
| db.collection.find(query, options).explain(options) |