MongDB
MongoDB简介
**MongoDB 是免费开源的跨平台 NoSQL 数据库,**命名源于英文单词 humongous,意思是「巨大无比」,可见开发组对 MongoDB 的 定位。与关系型数据库不同,MongoDB 的数据以类似于 JSON 格 式的二进制文档存储:
{
name: "McConaughey",
age: 18,
hobbies: ["travel", "swimming"]
}
文档型的数据存储方式有几个重要好处:
文档的数据类型可以对应 到语言的数据类型,如数组类型(Array)和对象类型(Object);
文档可以嵌套,有时关系型数据库涉及几个表的操作,在 MongoDB 中一次就能完成,可以减少昂贵的连接花销;
文档不对 数据结构加以限制,不同的数据结构可以存储在同一张表。
MongoDB的适用场景
**网站数据:**Mongo 非常适合实时的插入,更新与查询,并具备网站 实时数据存储所需的复制及高度伸缩性。
**缓存:**由于性能很高,Mongo 也适合作为信息基础设施的缓存层。 在系统重启之后,由Mongo搭建的持久化缓存层可以避免下层的数 据源过载。
**大尺寸、低价值的数据:**使用传统的关系型数据库存储一些大尺寸 低价值数据时会比较浪费,在此之前,很多时候程序员往往会选择 传统的文件进行存储。
**高伸缩性的场景:**Mongo 非常适合由数十或数百台服务器组成的数据库,Mongo 的路线图中已经包含对MapReduce 引擎的内置支持 以及集群高可用的解决方案。
**用于对象及JSON 数据的存储:**Mongo 的BSON 数据格式非常适合 文档化格式的存储及查询。
MongoDB的行业具体应用
游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分 等直接以内嵌文档的形式存储,方便查询、更新。
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中 会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能 将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋 友圈信息,通过地理位置索引实现附近的人、地点等功能。
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及 设备汇报的日志信息,并对这些信息进行多维度的分析。
直播,使用 MongoDB 存储用户信息、礼物信息等。
如何抉择是否使用MongoDB
应用特征 | Yes/No |
---|---|
应用不需要复杂事务及复杂join支持 | 必须yes |
新应用,需求会变,数据模型无法确定,想快速迭代开发 | ? |
应用需要2000-3000以上的读写QPS(更高也可以) | ? |
应用需要TB甚至 PB 级别数据存储 | ? |
应用发展迅速,需要能快速水平扩展 | ? |
应用需要大量的地理位置查询、文本查询 | ? |
应用需要99.999%高可用 | ? |
有一个yes就可以选择MongoDB,两个以上yes,选MongoDB绝对 不后悔
与关系型数据库比较
MongoDB与RDMS(关系型数据库)比较,如下图所示
RDMS | MongoDB |
---|---|
database(数据库) | database(数据库) |
table (表) | collection( 集合) |
row( 行) | document( BSON 文档) |
column (列) | field (字段) |
index(唯一索引、主键索引) | index (支持地理位置索引、全文索引 、哈希索引) |
join (主外键关联) | embedded Document (嵌套文档) |
primary key(指定1至N个列做主键) | primary key (指定_id field做为主键) |
什么是BSON
BSON是一种类似于JSON的二进制形式的存储格式,简称Binary JSON,它和JSON一样,支持内嵌的文档对象和数组对象,但是 BSON有JSON没有的一些数据类型,如Date和BinData类型。 BSON有三个特点:轻量性、可遍历性、高效性。
下表列出了MongoDB中Document可以出现的数据类型:
数据类型 | 说明 | document举例 |
---|---|---|
String | 字符串 | {key:“cba”} |
Integer | 整型数值 | {key:2} |
Boolean | 布尔型 | {key:true} |
Double | 双精度浮点数 | {key:0.23} |
ObjectId | 对象id,用于创建文档的id | {_id:new ObjectId()} |
Array | 数组 | {arr:[“jack”,“tom”]} |
Timestamp | 时间戳 | { createTime: new Timestamp() } |
object | 内嵌文档 | {student:{name:“zhangsan”,age:18}} |
null | 空值 | {key:null} |
Date或者ISODate | 日期时间 | {birthday:new Date()} |
Code | 代码 | {setPersonInfo:function(){}} |
MongoDB安装(Centos)
独立安装
进入/etc/yum.repos.d目录,创建文件
[root@192 yum.repos.d]# pwd
/etc/yum.repos.d
[root@192 yum.repos.d]# vim mongodb-org-5.0.repo
在文件内输入yum源地址
[mongodb-org-5.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/redhat/$releasever/mongodb-org/5.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-5.0.asc
安装之前先更新
yum update
开始安装
yum -y install mongodb-org
安装完成后,查看mongo的安装位置
whereis mongod
修改配置文件
#vim /etc/mongod.conf
bindIp: 172.0.0.1 改为 bindIp: 0.0.0.0 #(可以远程连接)
启动/停止/重启/查看
systemctl start mongod.service
systemctl stop mongod.service
systemctl restart mongod.service
systemctl status mongod.service
设置开机自启动
systemctl enable mongod.service
mongo shell 的启动
# 进入/usr/bin/目录
./mongo
指定主机和端口的方式启动
./mongo --host=主机IP --port=端口
docker安装
访问hub.docker.com,搜索mongo镜像
查看可用的镜像
获取你想要拉取的镜像
docker pull mongo:5.0.9-focal
查看已下载的镜像
docker images
创建挂载目录
mkdir -p /mnt/mongodb/data --创建保存数据目录
创建并运行 mongo 容器
docker run -itd --privileged=true --name mongo5
-p 27017:27017 -v /mnt/mongodb/data:/data/db
mongo:5.0.9-focal
使用GUI工具连接MongoDB
使用NosqlBooster For MongoDB客户端工具连接MongoDB数据 库
MongoDB架构
MongoDB逻辑结构
MongoDB 与 MySQL 中的架构相差不多,底层都使用了可插拔的 存储引擎以满足用户的不同需要。用户可以根据程序的数据特征选 择不同的存储引擎,在最新版本的 MongoDB 中使用了 WiredTiger 作为默认的存储引擎,WiredTiger 提供了不同粒度的并发控制和压缩机制,能够为不同种类的应用提供了最好的性能和存储率。
在存储引擎上层的就是 MongoDB 的数据模型和查询语言了,由于 MongoDB 对数据的存储与 RDBMS有较大的差异,所以它创建了一 套不同的数据模型和查询语言。
MongoDB数据模型
与SQL数据库不同,在SQL数据库中,在插入数据之前必须确定和 声明表的架构,默认情况下,MongoDB的集合不要求其文档具有相 同的架构。
结构灵活
单个集合中的文档不需要具有相同的字段集合,并且集合中的文档 之间的字段数据类型可能不同; 可灵活更改集合中文档的结构,如添加新字段、删除现有字段或将 字段值更改为新类型,将文档更新为新结构。
文档结构
内嵌
内嵌的方式指的是把相关联的数据保存在同一个文档结构之中。 MongoDB的文档结构允许一个字段或者一个数组内的值作为一个嵌 套的文档。
引用
引用方式通过存储数据引用信息来实现两个不同文档之间的关联,应 用程序可以通过解析这些数据引用来访问相关数据。
如何选择数据模型
选择内嵌:
数据对象之间有包含关系 ,一般是数据对象之间有一对多或者一对一 的关系 。
需要经常一起读取的数据。
有 map-reduce/aggregation 需求的数据放在一起,这些操作都只 能操作单个 collection。
选择引用:
当内嵌数据会导致很多数据的重复,并且读性能的优势又不足于覆 盖数据重复的弊端 。
需要表达比较复杂的多对多关系的时候 。
大型层次结果数据集 嵌套不要太深。
MongoDB存储引擎
存储引擎负责管理数据如何在磁盘和内存中存储,MongoDB支持多 种存储引擎,不同的存储引擎都有其在特定工作环境下的特点,选 择适合的存储引擎能够有效提高应用程序的性能。
WiredTiger存储引擎 (默认)
WiredTiger适合大多数工作场景,从MongoDB 3.2开始默认的存储 引擎是WiredTiger,3.2版本之前的默认存储引擎是MMAPv1, MongoDB 4.x版本不再支持MMAPv1存储引擎。
支持document级别并发操作
WiredTiger对写入操作使用document级并发控制。因此,多个客 户端可以同时修改集合的不同文档。对于大多数读写操作, WiredTiger使用乐观并发控制。WiredTiger仅在全局、数据库和集 合级别使用意向锁。当存储引擎检测到两个操作之间的冲突时,其 中一个操作将引发写入冲突,MongoDB会对用户透明地重试该操 作。
Snapshots and Checkpoints(快照和检查点)
WiredTiger使用多版本并发控制(MVCC)。在操作开始时, WiredTiger会向操作提供数据的point-in-time快照,快照显示了数 据在内存中的一致性视图。
从3.6版开始,MongoDB将WiredTiger配置为每隔60秒创建检查点 (即将快照数据写入磁盘)。在早期版本中,MongoDB将检查点设 置为在WiredTiger中每隔60秒或写入2 GB日志数据时(以先发生的 为准)对用户数据进行检查。
Journal(日志)
WiredTiger将日志与检查点结合使用,以确保数据的持久性。 WiredTiger日志将保留检查点之间的所有数据修改。如果 MongoDB在两个检查点之间退出,它将使用日志重播自上一个检查 点以来修改的所有数据
Compression(压缩)
使用WiredTiger存储引擎,MongoDB会对所有集合和索引进行压 缩,压缩以牺牲额外的CPU为代价,最大限度地减少了磁盘的使 用。默认情况下,WiredTiger对所有集合使用block compression,并对索引使用 prefix compression。
内存使用
对于WiredTiger,MongoDB利用WiredTiger内部缓存和文件系统 缓存。从MongoDB 3.4开始,默认WiredTiger内部缓存大小为以下 两者中的较大值:50% of (RAM - 1 GB) 256 MB
In-memory存储引擎
从MongoDB 企业版3.2.6版开始,In-Memory存储引擎是64位版本 中广泛使用(general availability GA)的一部分。除某些元数据和 诊断数据外,In-Memory存储引擎不维护任何磁盘上的数据,包括 配置数据,索引,用户凭据等。
In-Memory存储引擎设置
配置–storageEngine选项值为inMemory;如果使用配置文件,则 配置storage.engine
mongod --storageEngine inMemory --dbpath
<path>
配置–dbpath,如果使用配置文件则配置storage.dbPath。尽管InMemory存储引擎不会将数据写入文件系统,但它会在–dbpath中 维护小型元数据文件和诊断数据以及用于构建大型索引的临时文 件。
storage:
engine: inMemory
dbPath: <path>
并发(concurrency)
In-Memory存储引擎对于写入操作使用了document级并发控制。 多个客户端可以同时修改集合的不同文档。
内存使用
默认情况下,In-Memory存储引擎使用50%的物理RAM减去1 GB。 如果写操作的数据超过了指定的内存大小,则MongoDB返回错误.
"WT_CACHE_FULL: operation would overflow cache"
要指定新大小,可使用YAML格式配置文件的
storage:
engine: inMemory
dbPath: <path>
inMemory:
engineConfig:
inMemorySizeGB: <newSize>
事务
从MongoDB 4.2开始,复制集和分片集群上支持事务,其中:主成 员节点使用WiredTiger存储引擎,同时,辅助成员使用WiredTiger 存储引擎或In-Memory存储引擎。 在MongoDB 4.0中,只有使用WiredTiger存储引擎的复制集才支持 事务。
MongoDB命令
基本操作
查看数据库
show dbs;
切换数据库 如果没有对应的数据库则创建
use 数据库名;
创建集合
db.createCollection("集合名")
查看集合
show tables;
show collections;
删除集合
db.集合名.drop();
删除当前数据库
db.dropDatabase();
CRUD操作
添加文档
添加单个文档,如果集合不存在,会创建一个集合
db.collection.insertOne()
如果不指定id, MongoDB会使用ObjectId的value作为id
db.inventory.insertOne({
item: "canvas", qty: 100, tags: ["cotton"], size: {
h: 28, w: 35.5, uom: "cm" }})
添加多个文档
db.collection.insertMany()
如果不指定id, MongoDB会使用ObjectId的value作为id
db.inventory.insertMany([
{
item: "journal", qty: 25, tags: ["blank", "red"], size: {
h: 14, w: 21, uom: "cm" } },
{
item: "mat", qty: 85, tags: ["gray"], size: {
h: 27.9, w: 35.5, uom: "cm" } },
{
item: "mousepad", qty: 25, tags: ["gel", "blue"],size: {
h: 19, w: 22.85, uom: "cm"
}}])
查询文档
首先插入一批文档,再进行查询
db.inventory.insertMany( [
{
item: "journal", qty: 25, size: {
h: 14, w: 21, uom: "cm" }, status: "A" },
{
item: "notebook", qty: 50, size: {
h: 8.5, w: 11, uom: "in" }, status: "A" },
{
item: "paper", qty: 100, size: {
h: 8.5, w: 11, uom: "in" }, status: "D" },
{
item: "planner", qty: 75, size: {
h: 22.85, w: 30, uom: "cm" }, status: "D" },
{
item: "postcard", qty: 45, size: {
h: 10, w: 15.25, uom: "cm" }, status: "A" }
]);
查询集合所有文档
db.inventory.find({
})
查询指定内容的文档,匹配1条
db.inventory.find( {
size: {
h: 14, w: 21, uom:"cm" } } )
匹配0条,原因是顺序不匹配
db.inventory.find( {
size: {
w: 21, h: 14, uom: "cm" } } )
匹配size中uom属性为“in”的文档
db.inventory.find( {
"size.uom": "in" } )
匹配size中h属性值小于15的文档
db.inventory.find( {
"size.h": {
$lt: 15 } } )
匹配h属性小于15并且uom属性为“in”,并且“status”属性为"D"的文 档
db.inventory.find( {
"size.h": {
$lt: 15 }, "size.uom": "in", status: "D" } )
s
更新文档
插入下列文档,供更新操作
db.inventory.insertMany([
{
item: "canvas", qty: 100, size: {
h: 28, w: 35.5, uom: "cm" }, status: "A" },
{
item: "journal", qty: 25, size: {
h: 14, w: 21, uom: "cm" }, status: "A" },
{
item: "mat", qty: 85, size: {
h: 27.9, w: 35.5, uom: "cm" }, status: "A" },
{
item: "mousepad", qty: 25, size: {
h: 19, w: 22.85, uom: "cm" }, status: "P" },
{
item: "notebook", qty: 50, size: {
h: 8.5, w: 11, uom: "in" }, status: "P" },
{
item: "paper", qty: 100, size: {
h: 8.5, w: 11, uom: "in" }, status: "D" },
{
item: "planner", qty: 75, size: {
h: 22.85, w: 30, uom: "cm" }, status: "D" },
{
item: "postcard", qty: 45, size: {
h: 10, w: 15.25, uom: "cm" }, status: "A" },
{
item: "sketchbook", qty: 80, size: {
h: 14, w: 21, uom: "cm" }, status: "A" },
{
item: "sketch pad", qty: 95, size: {
h: 22.85, w:
30.5, uom: "cm" }, status: "A" }]);
更新item值为“paper”的第一个文档 将它的size.uom设置为“cm”,status值设置为"P" 并且把lastModified字段更新为当前时间,如果该字段不存在,则 生成一个
db.inventory.updateOne(
{
item: "paper" },
{
$set: {
"size.uom": "cm", status: "P" },
$currentDate: {
lastModified: true }}
)
#更新返回
#参数一:更新成功;参数二:匹配多少条;参数三:成功多少条。
#{ "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }
更新qty属性值小于50的文档 将它的size.uom设置为“in”,status值设置为"P" 并且把lastModified字段更新为当前时间,如果该字段不存在,则 生成一个
db.inventory.updateMany(
{
"qty": {
$lt: 50 } },
{
$set: {
"size.uom": "in", status: "P" },
$currentDate: {
lastModified: true }
}
)
把item属性为“paper”的文档替换成下面的内容
db.inventory.replaceOne(
{
item: "paper" },{
item: "paper", instock:
[ {
warehouse: "A", qty: 60 }, {
warehouse:
"B", qty: 40 } ] })
删除文档
删除集合所有文档
db.inventory.deleteMany({
})
删除指定条件的文档
db.inventory.deleteMany({
status : "A" })
最多删除1个指定条件的文档
db.inventory.deleteOne( {
status: "D" } )
与SQL语法的对应
聚合操作
通过聚合操作可以处理多个文档,并返回计算后的结果。
对多个文档进行分组
对分组的文档执行操作并返回单个结果
分析数据变化
聚合管道
分别由多个阶段来处理文档,