当前位置 : 首页 » 文章分类 :  开发  »  MongoDB

MongoDB

MongoDB 使用笔记


简介

MongoDB 是 C++ 编写的一个基于分布式文件存储的开源数据库系统。
在高负载的情况下,添加更多的节点,可以保证服务器性能。
MongoDB 旨在为 Web 应用提供可扩展的高性能数据存储解决方案。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。
MongoDB 文档类似于 Json 对象。字段值可以包含其他文档,数组及文档数组。

MongoDB与Redis比较

MongoDB 文件存储是 Bson 格式,类似 Json, 或自定义的二进制格式。MongoDB 与 Redis性能都很依赖内存的大小,MongoDB有丰富的数据表达、索引;最类似于关系数据库,支持丰富的查询语言,Redis数据丰富,较少的 IO,这方面MongoDB优势明显。
MongoDB 不支持事务,靠客户端自身保证,Redis 支持事务,比较弱,仅能保证事务中的操作按顺序执行,这方面Redis优于MongoDB。
MongoDB 对海量数据的访问效率提升,Redis 较小数据量的性能及运算,这方面MongoDB优于Redis。
MongoDB 有 MapReduce 功能,提供数据分析,Redis没有,这方面MongoDB优于Redis。

MongoDB与关系数据库术语对比

mongodb与关系型数据库的对比

关系数据库概念 MongoDB概念 说明
database database 数据库
table collection 数据库表/集合
row document 数据记录行/文档
column field 数据字段/域
index index 索引
table joins 表连接,MongoDB不支持(嵌套文档)
primary key primary key 主键,MongoDB自动将_id字段设置为主键
aggregate(group) aggregate(pipeline mapReduce) 聚合

场景

适用场景

1)实时的CRU操作,例如网站、论坛的实时数据处理。它非常适合实时的插入、更新与查询,并具备网站实时数据存储所需的复制及高度伸缩性。
2)缓存。由于性能很高,它适合作为信息基础设施的缓存层。在系统重启之后,由它搭建的持久化缓存层可以避免下层的数据源过载。
3)高伸缩性的场景,分布式集群动态增删节点。非常适合由数十或数百台服务器组成的数据库,内部包含对 MapReduce 引擎的内置支持。
4)用于对象及 JSON 数据的存储:Mongo 的 BSON 数据格式非常适合文档化格式的存储及查询

不适用场景

1)高度事务性操作,如银行或会计系统。
2)传统商业智能(BI)应用,如提供高度优化的查询方式。
3)复杂的跨文档(表)级联查询。

选型决策

列出应用特征的 Yes/No 选项

1、应用不需要事务及复杂 join 支持必须 Yes

2、新应用,需求会变,数据模型无法确定,想快速迭代开发?
3、应用需要2000-3000以上的读写QPS(更高也可以)?
4、应用需要TB甚至 PB 级别数据存储?
5、应用发展迅速,需要能快速水平扩展?
6、应用要求存储的数据不丢失?
7、应用需要99.999%高可用?
8、应用需要大量的地理位置查询、文本查询?

如果上述有1个 Yes,可以考虑 MongoDB,2个及以上的 Yes,选择MongoDB绝不会后悔

场景举例

游戏场景,使用 MongoDB 存储游戏用户信息,用户的装备、积分等直接以内嵌文档的形式存储,方便查询、更新
物流场景,使用 MongoDB 存储订单信息,订单状态在运送过程中会不断更新,以 MongoDB 内嵌数组的形式来存储,一次查询就能将订单所有的变更读取出来。
社交场景,使用 MongoDB 存储存储用户信息,以及用户发表的朋友圈信息,通过地理位置索引实现附近的人、地点等功能
物联网场景,使用 MongoDB 存储所有接入的智能设备信息,以及设备汇报的日志信息,并对这些信息进行多维度的分析
视频直播,使用 MongoDB 存储用户信息、礼物信息等


Mongo数据类型

String 字符串。存储数据常用的数据类型。在 MongoDB 中,UTF-8 编码的字符串才是合法的。
Integer 整型数值。用于存储数值。根据你所采用的服务器,可分为 32 位或 64 位。
Boolean 布尔值。用于存储布尔值(真/假)。
Double 双精度浮点值。用于存储浮点值。
Min/Max keys 将一个值与 BSON(二进制的 JSON)元素的最低值和最高值相对比。
Arrays 用于将数组或列表或多个值存储为一个键。
Timestamp 时间戳。记录文档修改或添加的具体时间。
Object 用于内嵌文档。
Null 用于创建空值。
Symbol 符号。该数据类型基本上等同于字符串类型,但不同的是,它一般用于采用特殊符号类型的语言。
Date 日期时间。用 UNIX 时间格式来存储当前日期或时间。你可以指定自己的日期时间:创建 Date 对象,传入年月日信息。
Object ID 对象 ID。用于创建文档的 ID。
Binary Data 二进制数据。用于存储二进制数据。
Code 代码类型。用于在文档中存储 JavaScript 代码。
Regular expression 正则表达式类型。用于存储正则表达式。


磁盘空间

drop db 会立即释放磁盘空间。
drop collection 不会立即释放空间,但被删除的collection占用的空间可以被复用。


内存

MongoDB如何使用内存

目前,MongoDB使用的是内存映射存储引擎,它会把磁盘IO操作转换成内存操作,如果是读操作,内存中的数据起到缓存的作用,如果是写操作,内存还可以把随机的写操作转换成顺序的写操作,总之可以大幅度提升性能。MongoDB并不干涉内存管理工作,而是把这些工作留给操作系统的虚拟缓存管理器去处理,这样的好处是简化了MongoDB的工作,但坏处是你没有方法很方便的控制MongoDB占多大内存,事实上MongoDB会占用所有能用的内存,所以最好不要把别的服务和MongoDB放一起。

如何强行收回内存

1、重启mongodb,或者调用 db.runCommand({closeAllDatabases:1}) 来清除内存
2、使用Linux命令清除缓存中的数据:echo 3 > /proc/sys/vm/drop_caches

wiredTigerCacheSizeGB

mongod 提供了额外的可选参数 wiredTigerCacheSizeGB 来控制 WiredTiger 存储引擎所占用的 cache size
例如

wiredTigerCacheSizeGB=10

注意:
1、若不设置 wiredTigerCacheSizeGB 大小,mongodb 服务会根据本机内存设置内存大小
2、cache size设置较低,同时mongodb复杂查询很频繁的话,会有延迟发生。


索引

索引通常能够极大的提高查询的效率,如果没有索引,MongoDB 在读取数据时必须扫描集合中的每个文件并选取那些符合查询条件的记录。

db.col.getIndexes() 查看索引

> db.msg_send.getIndexes();
[
    {
        "v" : 2,
        "key" : {
            "_id" : 1
        },
        "name" : "_id_"
    },
    {
        "v" : 2,
        "key" : {
            "expireAt" : 1
        },
        "name" : "expireAt",
        "expireAfterSeconds" : NumberLong(0)
    }
]

db.col.totalIndexSize() 查看索引大小

db.col.dropIndexes() 删除所有索引

db.col.dropIndex(“idx_name”) 删除指定索引

db.col.createIndex() 创建索引

MongoDB 使用 createIndex() 方法来创建索引。
注意在 3.0.0 版本前创建索引方法为 db.collection.ensureIndex(), 之后的版本使用了 db.collection.createIndex() 方法,ensureIndex() 还能用,但只是 createIndex() 的别名。

db.collection.createIndex(keys, options)
keys 指定一个或多个索引字段,例如 {"name":1}, {"name":1, "age":-1}, 1是升序,-1是降序
options 选项指定索引特性
例如在后台创建索引 db.collection.createIndex({"name":1}, {background: true})

background Boolean 建索引过程会阻塞其它数据库操作,background可指定以后台方式创建索引,即增加 “background” 可选参数。 默认值为false。
unique Boolean 建立的索引是否唯一。指定为true创建唯一索引。默认值为false.
name string 索引的名称。如果未指定,MongoDB的通过连接索引的字段名和排序顺序生成一个索引名称。
dropDups Boolean 3.0+版本已废弃。在建立唯一索引时是否删除重复记录,指定 true 创建唯一索引。默认值为 false.
sparse Boolean 对文档中不存在的字段数据不启用索引;这个参数需要特别注意,如果设置为true的话,在索引字段中不会查询出不包含对应字段的文档.。默认值为 false.
expireAfterSeconds integer 指定一个以秒为单位的数值,完成 TTL 设定,设定集合的生存时间。
v index version 索引的版本号。默认的索引版本取决于mongod创建索引时运行的版本。
weights document 索引权重值,数值在 1 到 99,999 之间,表示该索引相对于其他索引字段的得分权重。
default_language string 对于文本索引,该参数决定了停用词及词干和词器的规则的列表。 默认为英语
language_override string 对于文本索引,该参数指定了包含在文档中的字段名,语言覆盖默认的language,默认值为 language.

TTL索引设置数据生存时间

TTL 索引是一种特殊索引,通过这种索引 MongoDB 会过一段时间后自动移除集合中的文档。
可以设置在指定的时间段后或在指定的时间点过期,MongoDB 有独立线程去清除数据,类似于设置定时自动删除任务。

TTL 索引不能保证过期数据会被立刻删除。在文档过期和 MongoDB 从数据库中删除文档之间,可能会有延迟。
删除过期数据的后台任务每隔 60 秒运行一次。所以,在文档过期之后和后台任务运行结束之前,文档会依然存在于集合中。

Timing of the Delete Operation
https://docs.mongodb.com/manual/core/index-ttl/#timing-of-the-delete-operation

通过 db.collection.createIndex() 命令配合 expireAfterSeconds 选项来对集合中某个字段做 TTL 索引。
这个字段必须是 Date 类型或者是一个包含 Date 类型值的数组字段
如果这个键是一个数组,那么当其中最早过期的时间得到匹配时,这篇文档就会过期失效了。

指定一段时间后过期

例如设置以下数据在 3600 秒之后过期

{
    "_id": "5f43d5c00b34962beb026aad",
    "createdAt": Date(),
    "requestTime": 1598281152423,
    "logId": "1598281152423-6245975993217447",
}

createdAt 字段是插入时间,在其上创建正序索引,指定 expireAfterSeconds 3600 秒之后过期,含义是:在 createdAt 字段的值的时刻基础上,再加上 3600 秒之后的那个时间点过期。
db.logs.createIndex({ "createdAt": 1 }, {expireAfterSeconds: 3600 })

指定过期时间点

有时为了避开访问高峰期,希望在凌晨某个时间点过期,此时可以在文档中加入一个指定过期时间点的字段,然后将 expireAfterSeconds 设为 0
例如

{
    "_id": "5f43d5c00b34962beb026aad",
    "createdAt": Date(),
    "expireAt": ISODate("2020-09-02T11:44:11.528Z"),
    "logId": "1598281152423-6245975993217447",
}

然后在 expireAt 字段创建正序索引,指定 expireAfterSeconds 为 0, 所以 Mongo 会在 expireAt 的时间点加上 0 秒后的时间点删除数据。
db.logs.createIndex({ "expireAt": 1 }, {"expireAfterSeconds": 0})


mongostat

mongostat 是 mongodb 自带的状态检测工具,在命令行下使用,会间隔固定时间(默认1s)获取 mongodb 的当前运行状态,并输出。


Sharded cluster

MongoDB Sharded cluster架构原理
https://developer.aliyun.com/article/32434


mongos

Mongos 是 MongoDB 分片集群的访问入口,Mongos 收到 Client 访问请求,会根据从 Config Server 获取的路由表将请求转发到后端对应的 Shard 上。

分片集群Mongos到Shard请求管理
https://mongoing.com/archives/3983


Mac Brew安装MongoDB

MongoDB 已经宣布不再开源,从2019年9月2日开始 HomeBrew 也从核心仓库当中移除了 mongodb 模块

MongoDB 官方提供了一个单独的 HomeBrew 的社区版本安装 Tap
https://github.com/mongodb/homebrew-brew

brew tap 安装 mongodb/brew
brew tap mongodb/brew

安装最新 mongodb 社区版
brew install mongodb-community

指定版本安装
brew install mongodb-community@4.4

安装目录
/usr/local/Cellar/mongodb-community/4.4.5

使用brew services启动并添加开机启动:
brew services start mongodb/brew/mongodb-community

前台启动
mongod --config /usr/local/etc/mongod.conf


启动/停止mongodb

启动MongoDB

1、启动
mongod –dbpath /home/user1/mongodb/data –logpath /home/user1/mongodb/log/logs –fork
mongo服务启动必须要指定文件存放的目录dbpath,–fork以守护进程运行,如果带—fork参数则必须要指定—logpath即日志存放的位置

2、指定配置文件启动
mongod -f conf/mongo_conf.conf

mongod 和 mongo 的区别
mongod 是 MongoDB 的服务端后台进程,mongo 是客户端。

停止MongoDB

1、查看进程并 kill
ps aux|grep mongod
kill -9 pid

2、在客户端中使用 shutdown 命令

> use admin
switched to db admin
> db.auth('admin','123456')
> db.shutdownServer()

mongo连接

mongo 连接本机 27017 端口的 mongo 等于 mongo localhost:27017mongo 127.0.0.1:27017

mongo 192.168.1.100:27017 指定 ip 和端口连接 mongo

# mongo localhost:27019
MongoDB shell version: 3.2.16
connecting to: localhost:27019/test

mongo 192.168.1.100:27017/test 指定ip、端口、数据库名连接

mongo 192.168.1.200:27017/test -u user -p password 指定ip、端口、用户名、密码、数据库名连接

Mongo查看版本号

mongo –version

未登录 mongo 时 mongo --versionmongod --version

mongo --version
MongoDB shell version v4.4.0
Build Info: {
    "version": "4.4.0",
    "gitVersion": "563487e100c4215e2dce98d0af2a6a5a2d67c5cf",
    "modules": [],
    "allocator": "system",
    "environment": {
        "distarch": "x86_64",
        "target_arch": "x86_64"
    }
}

db.version() MongoDB查看版本号

已登录 mongo 后:

> db.version();
4.4.0

MongoDB时间少8小时

现象:
通过 Spring Boot Data MongoDB 保存到 mongo 中的时间,在 mongo shell db.col.find(); 查看时少 8 个小时,但 Java 代码中保存日志和查询出来的时间都是正常的。

原因:
MongoDB 自带的 Date 是 UTC/GMT 时间,中国是东八区(UTC+8)。
MongoDB 中的 Date 类型数据只保存绝对时间值,不保存时区信息,因此“显示的时间”取决于 MongoDB 的客户端设置。

解决:
MongoDB 服务端只能以 UTC/GMT 存储时间,不支持时区设置,只能在各个客户端修改时区
如果使用可视化工具 Robomongo 的话,可以通过”Options” - “Display Dates in…” - “Local Timezone” 来设置显示本地时间。


mongo命令行操作

查看所有账号信息

>  use admin
switched to db admin
> db.auth('admin','123456')
1
> db.system.users.find().pretty()

db.adminCommand 迁移collection

db1 中的 test1 改名为 test2
db.adminCommand({renameCollection: “db1.test1”, to: “db1.test2”})

还可以跨 db 迁移 collection, 比如将 db1.test1 迁移到 db2.test2
db.adminCommand({renameCollection: “db1.test1”, to: “db2.test2”})
此时会将 db1.test1 的数据拷贝到 db2.test2, 如果 db2 中已有 test2 集合会将其 drop 掉。

renameCollection
https://docs.mongodb.com/manual/reference/command/renameCollection/

show dbs 查看数据库

show dbsshow databases 查看数据库

> show dbs
admin   0.000GB
config  0.000GB
local   0.000GB

db 查看当前数据库

use db 切换/创建数据库

mongo 中创建数据库采用的也是 use 命令,如果 use 后面跟的数据库名不存在,那么 mongo 将会新建该数据库。
不过,实际上只执行 use 命令后,mongo 是不会新建该数据库的,直到你像该数据库中插入了数据。

db.dropDatabase() 删除db

> db.dropDatabase()
{ "dropped" : "test", "ok" : 1 }

show collections 查看当前库中的集合

db.createCollection(name, options) 创建集合

name: 要创建的集合名称
options: 可选参数, 指定有关内存大小及索引的选项

capped 布尔(可选)如果为 true,则创建固定集合。固定集合是指有着固定大小的集合,当达到最大值时,它会自动覆盖最早的文档。当该值为 true 时,必须指定 size 参数。
autoIndexId 布尔 3.2 之后不再支持该参数。(可选)如为 true,自动在 _id 字段创建索引。默认为 false。
size 数值 (可选)为固定集合指定一个最大值,即字节数。如果 capped 为 true,也需要指定该字段。
max 数值(可选)指定固定集合中包含文档的最大数量。

注意:MongoDB 中不需要单独创建集合。当插入文档到某个集合时,MongoDB 会自动创建不存在的集合

db.col.drop() 删除集合

db.col.renameCollection() 集合重命名

修改 msg 集合名为 msg_bak_531

> db.msg.renameCollection("msg_bak_531");
{ "ok" : 1 }

db.col.insert() 插入文档

如果集合 col 在该数据库中不存在, MongoDB 会自动创建该集合并插入文档。

db.col.save() 插入或更新文档

save() 如果 _id 主键存在则更新数据,如果不存在就插入数据。
该方法新版本中已废弃,可以使用 db.collection.insertOne()db.collection.replaceOne() 来代替。

db.col.insertMany() 批量插入数据

db.col.find() 查看文档

> db.col.find();
{ "_id" : ObjectId("605852c8268f6ff446491871"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }
{ "_id" : ObjectId("6058672a268f6ff446491872"), "title" : "MongoDB 教程", "description" : "MongoDB 是一个 Nosql 数据库", "by" : "菜鸟教程", "url" : "http://www.runoob.com", "tags" : [ "mongodb", "database", "NoSQL" ], "likes" : 100 }

条件查询

查询 url 是指定值的文档
db.msg_send.find({"url": "http://mc-service:8080/api/v1/mock/callback"});

limit() 指定返回结果数

> db.col.find().limit(2);

skip() 指定偏移量

count(“a”:null) 查询字段为空或不存在的文档

> db.col.find({"type":null}).limit(2);

db.col.count() 查看集合中的文档数

count(“a”:null) 查询字段为空或不存在的文档个数

> db.col.count({"type":null});
6896

db.col.deleteMany() 条件删除

删除 type 字段为 null 或不存在的文档

> db.col.deleteMany({"type":null});
{ "acknowledged" : true, "deletedCount" : 6896 }

上一篇 typesafe.config与HOCON

下一篇 Apache-Commons-Validator 笔记

阅读
评论
4.6k
阅读预计18分钟
创建日期 2020-08-19
修改日期 2021-06-01
类别

页面信息

location:
protocol:
host:
hostname:
origin:
pathname:
href:
document:
referrer:
navigator:
platform:
userAgent:

评论