MongoDB
MongoDB
什么是MongoDB ?
MongoDB 是一个基于分布式文件存储的开源数据库。由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。
MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
MongoDB 将数据存储为一个文档,数据结构由键值(key=>value)对组成。MongoDB 文档类似于 JSON 对象。字段值可以包含其他文档,数组及文档数组。
主要特点
- MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。
- 你可以在MongoDB记录中设置任何属性的索引 (如:FirstName="Sameer",Address="8 Gandhi Road")来实现更快的排序。
- 你可以通过本地或者网络创建数据镜像,这使得MongoDB有更强的扩展性。
- 如果负载的增加(需要更多的存储空间和更强的处理能力) ,它可以分布在计算机网络中的其他节点上这就是所谓的分片。
- Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。
- MongoDB 使用update()命令可以实现替换完成的文档(数据)或者一些指定的数据字段 。
- MongoDB中的Map/reduce主要是用来对数据进行批量处理和聚合操作。
- Map和Reduce。Map函数调用emit(key,value)遍历集合中所有的记录,将key与value传给Reduce函数进行处理。
- Map函数和Reduce函数是使用Javascript编写的,并可以通过db.runCommand或mapreduce命令来执行MapReduce操作。
- GridFS是MongoDB中的一个内置功能,可以用于存放大量小文件。
- MongoDB允许在服务端执行脚本,可以用Javascript编写某个函数,直接在服务端执行,也可以把函数的定义存储在服务端,下次直接调用即可。
- MongoDB支持各种编程语言:RUBY,PYTHON,JAVA,C++,PHP,C#,Go等多种语言。
- MongoDB安装简单。
安装
去官网下载你所要安装的版本
https://www.mongodb.com/try/download/community
这里以在CentOS7安装为例
部署
下载完安装包,并解压 tgz
tar -zxvf mongodb-linux-x86_64-rhel70-5.0.6.tgz
#解压后的文件
mongodb-linux-x86_64-rhel70-5.0.6/LICENSE-Community.txt
mongodb-linux-x86_64-rhel70-5.0.6/MPL-2
mongodb-linux-x86_64-rhel70-5.0.6/README
mongodb-linux-x86_64-rhel70-5.0.6/THIRD-PARTY-NOTICES
mongodb-linux-x86_64-rhel70-5.0.6/bin/install_compass
mongodb-linux-x86_64-rhel70-5.0.6/bin/mongo
mongodb-linux-x86_64-rhel70-5.0.6/bin/mongod
mongodb-linux-x86_64-rhel70-5.0.6/bin/mongos
mv mongodb-linux-x86_64-rhel70-5.0.6 /opt/module/mongodb
cd /opt/module/mongodb/
mkdir conf data log
配置
vim conf/mongodb.conf
写入如下内容
storage:
dbPath: "/opt/module/mongodb/data/"
engine: wiredTiger
journal:
enabled: true
systemLog:
destination: file
path: "/opt/module/mongodb/log/mongodb.log"
logAppend: true
processManagement:
fork: true
pidFilePath: "/opt/module/mongodb/mongod.pid"
net:
port: 27017
启动
#启动
./bin/mongod -f conf/mongodb.conf
about to fork child process, waiting until server is ready for connections.
forked process: 27217
child process started successfully, parent exiting
#查看端口
netstat -nlpt |grep 27017
tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN 27217/./bin/mongod
使用shell客户端连接
./bin/mongo --port 27017
或者
./bin/mongo
Implicit session: session { "id" : UUID("a0f6e723-44ff-40b9-bbc2-1ad3792df183") }
MongoDB server version: 5.0.6
================
Warning: the "mongo" shell has been superseded by "mongosh",
which delivers improved usability and compatibility.The "mongo" shell has been deprecated and will be removed in
an upcoming release.
For installation instructions, see
https://docs.mongodb.com/mongodb-shell/install/
================
---
The server generated these startup warnings when booting:
2022-03-24T22:07:44.464+08:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2022-03-24T22:07:44.464+08:00: You are running this process as the root user, which is not recommended
2022-03-24T22:07:44.464+08:00: This server is bound to localhost. Remote systems will be unable to connect to this server. Start the server with --bind_ip <address> to specify which IP addresses it should serve responses from, or with --bind_ip_all to bind to all interfaces. If this behavior is desired, start the server with --bind_ip 127.0.0.1 to disable this warning
2022-03-24T22:07:44.465+08:00: /sys/kernel/mm/transparent_hugepage/enabled is 'always'. We suggest setting it to 'never'
2022-03-24T22:07:44.466+08:00: /sys/kernel/mm/transparent_hugepage/defrag is 'always'. We suggest setting it to 'never'
---
---
Enable MongoDB's free cloud-based monitoring service, which will then receive and display
metrics about your deployment (disk utilization, CPU, operation statistics, etc).
The monitoring data will be available on a MongoDB website with a unique URL accessible to you
and anyone you share the URL with. MongoDB may use this information to make product
improvements and to suggest MongoDB products and deployment options to you.
To enable free monitoring, run the following command: db.enableFreeMonitoring()
To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
---
>
简单使用
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
> use test
switched to db test
> db.something.insert({ x: 1 })
WriteResult({ "nInserted" : 1 })
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
> show tables
something
> db.something.findOne()
{ "_id" : ObjectId("623c7deaed453ca6f996ba6c"), "x" : 1 }
> db.stats()
{
"db" : "test",
"collections" : 1,
"views" : 0,
"objects" : 1,
"avgObjSize" : 33,
"dataSize" : 33,
"storageSize" : 20480,
"indexes" : 1,
"indexSize" : 20480,
"totalSize" : 40960,
"scaleFactor" : 1,
"fsUsedSize" : 17353003008,
"fsTotalSize" : 157821173760,
"ok" : 1
}
>
停止
方式一:使用 kill 命令
kill -2 `cat mongod.pid`
方式二:使用 db.shutdownServer()命令
> use admin
switched to db admin
> db.shutdownServer()
server should be down...
>
概念
mongodb中基本的概念是文档、集合、数据库
数据库
一个mongodb中可以建立多个数据库。
MongoDB的默认数据库为"db",该数据库存储在data目录中。
MongoDB的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中。
"show dbs" 命令可以显示所有数据的列表。
> show dbs
admin 0.000GB
config 0.000GB
local 0.000GB
test 0.000GB
>
执行 "db" 命令可以显示当前数据库对象或集合。
> db
test
>
运行"use"命令,可以连接到一个指定的数据库。
> use local
switched to db local
> db
local
>
以上实例命令中,"local" 是你要链接的数据库。
数据库也通过名字来标识。数据库名可以是满足以下条件的任意UTF-8字符串。
- 不能是空字符串("")。
- 不得含有' '(空格)、.、$、/、\和\0 (空字符)。
- 应全部小写。
- 最多64字节。
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库。
- admin: 从权限的角度来看,这是"root"数据库。要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限。一些特定的服务器端命令也只能从这个数据库运行,比如列出所有的数据库或者关闭服务器。
- local: 这个数据永远不会被复制,可以用来存储限于本地单台服务器的任意集合
- config: 当Mongo用于分片设置时,config数据库在内部使用,用于保存分片的相关信息。
文档(Document)
文档是一组键值(key-value)对(即 BSON)。MongoDB 的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是 MongoDB 非常突出的特点。
一个简单的文档例子如下:
{"city":"guangzhou", "name":"lalala"}
需要注意的是:
- 文档中的键/值对是有序的。
- 文档中的值不仅可以是在双引号里面的字符串,还可以是其他几种数据类型(甚至可以是整个嵌入的文档)。
- MongoDB区分类型和大小写。
- MongoDB的文档不能有重复的键。
- 文档的键是字符串。除了少数例外情况,键可以使用任意UTF-8字符。
文档键命名规范:
- 键不能含有\0 (空字符)。这个字符用来表示键的结尾。
- .和$有特别的意义,只有在特定环境下才能使用。
- 以下划线"_"开头的键是保留的(不是严格要求的)。
集合
集合就是 MongoDB 文档组,类似于 RDBMS (关系数据库管理系统:Relational Database Management System)中的表格。
集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性。
比如,我们可以将以下不同数据结构的文档插入到集合中:
{"site":"www.baidu.com"}
{"site":"www.google.com","name":"Google"}
{"site":"www.mongodb.com","name":"mongodb","num":3}
当第一个文档插入时,集合就会被创建。
合法的集合名
- 集合名不能是空字符串""。
- 集合名不能含有\0字符(空字符),这个字符表示集合名的结尾。
- 集合名不能以"system."开头,这是为系统集合保留的前缀。
- 用户创建的集合名字不能含有保留字符。有些驱动程序的确支持在集合名里面包含,这是因为某些系统生成的集合中包含该字符。除非你要访问这种系统创建的集合,否则千万不要在名字里出现$。
如下实例:
db.col.findOne()
capped collections
Capped collections 就是固定大小的collection。
它有很高的性能以及队列过期的特性(过期按照插入的顺序). 有点和 "RRD" 概念类似。
Capped collections 是高性能自动的维护对象的插入顺序。它非常适合类似记录日志的功能和标准的 collection 不同,你必须要显式的创建一个capped collection,指定一个 collection 的大小,单位是字节。collection 的数据存储空间值提前分配的。
Capped collections 可以按照文档的插入顺序保存到集合中,而且这些文档在磁盘上存放位置也是按照插入顺序来保存的,所以当我们更新Capped collections 中文档的时候,更新后的文档不可以超过之前文档的大小,这样话就可以确保所有文档在磁盘上的位置一直保持不变。
由于 Capped collection 是按照文档的插入顺序而不是使用索引确定插入位置,这样的话可以提高增添数据的效率。MongoDB 的操作日志文件 oplog.rs 就是利用 Capped Collection 来实现的。
要注意的是指定的存储大小包含了数据库的头信息。
db.createCollection("mycoll", {capped:true, size:100000})
- 在 capped collection 中,你能添加新的对象。
- 能进行更新,然而,对象不会增加存储空间。如果增加,更新就会失败 。
- 使用 Capped Collection 不能删除一个文档,可以使用 drop() 方法删除 collection 所有的行。
- 删除之后,你必须显式的重新创建这个 collection。
- 在32bit机器中,capped collection 最大存储为 1e9( 1X109)个字节。
固定集合可以声明 collection 的容量大小,其行为类似于循环队列。数据插入时,新文档会被插入到队列的末尾,如果队列已经被占满,那么最老的文档会被之后插入的文档覆盖。
固定集合特性:固定集合很像环形队列,如果空间不足,最早的文档就会被删除,为新的文档腾出空间。一般来说,固定集合适用于任何想要自动淘汰过期属性的场景。
固定集合应用场景
比如日志文件,聊天记录,通话信息记录等只需保留最近某段时间内的应用场景,都会使用到MongoDB 的固定集合。
固定集合的优点
- 写入速度提升。固定集合中的数据被顺序写入磁盘上的固定空间,所以,不会因为其他集合的一些随机性的写操作而“中断”,其写入速度非常快(不建立索引,性能更好)。
- 固定集合会自动覆盖掉最老的文档,因此不需要再配置额外的工作来进行旧文档删除。设置 Job进行旧文档的定时删除容易形成性能的压力毛刺。
固定集合非常适合用于记录日志等场景。
固定集合的创建
不同于普通集合,固定集合必须在使用前显式创建。
例如,创建固定集合 coll_testcapped,大小限制为 1024 个字节。
db.createCollection("coll_testcapped",{capped:true,size:1024});
注意事项
-
固定集合创建之后就不可以改变,只能将其删除重建。
-
普通集合可以使用 convertToCapped 转换固定集合,但是固定集合不可以转换为普通集合。
-
创建固定集合,为固定集合指定文档数量限制时(指参数 max),必须同时指定固定集合的大小(指参数 size)。不管先达到哪一个限制,之后插入的新文档都会把最老的文档移除集合。
-
使用 convertToCapped 命令将普通集合转换固定集合时,既有的索引会丢失,需要手动创建。并且,此转换命令没有限制文档数量的参数(即没有 max 的参数选项)。
-
不可以对 固定集合 进行分片。
-
对固定集合中的文档可以进行更新(update)操作,但更新不能导致文档的 Size 增长或缩小,否则更新失败。
假如集合中有一个 key,其 value 对应的数据长度为 100 个字节,如果要更新这个 key 对应的 value,
更新后的值也必须为 100 个字节,大于 100 个字节不可以,小于 100 个字节也不可以。
报错信息为: Cannot change the size of a document in a capped collection : XXXX( XXXX 代表某个数据
字) !=XXXX。 -
不可以对固定集合执行删除文档操作,但可以删除整个集合。
删除文档时,报错信息为: cannot remove from a capped collection: XXXX -
还有一定需要注意,对集合估算 size 时,不要依据集合的 storageSize ,而是依据集合的 size。storageSize 是 wiredTiger 存储引擎采用高压缩算法压缩后的
元数据
元数据是一个预留空间,在对数据库或应用程序结构执行修改时,其内容可以由数据库自动更新。
元数据是系统中各类数据描述的集合,是执行详细的数据收集与数据分析的主要途径。
元数据最重要的作用是作为一个分析阶段的工具,任何字典最重要的操作是查询,在结构化分析中,元数据的作用是给每一个结点加上定义与说明。换句话说,数据流图上所有节点的定义和解释的集合就是元数据,而且在元数据中建立严密一致的定义有助于提高需求分析人员和用户沟通的效率。
数据库的信息是存储在集合中。它们使用了系统的命名空间:
dbname.system.*
在MongoDB数据库中名字空间
集合命名空间 | 描述 |
---|---|
dbname.system.namespaces | 列出所有名字空间。 |
dbname.system.indexes | 列出所有索引。 |
dbname.system.profile | 包含数据库概要(profile)信息。 |
dbname.system.users | 列出所有可访问数据库的用户。 |
dbname.local.sources | 包含复制对端(slave)的服务器信息和状态。 |
对于修改系统集合中的对象有如下限制。
在{{system.indexes}}插入数据,可以创建索引。但除此之外该表信息是不可变的(特殊的drop index命令将自动更新相关信息)。
{{system.users}}是可修改的。 {{system.profile}}是可删除的。
MongoDB 数据类型-BSON
BSON 是 JSON 的“二进制版本”, MongoDB 使用 BSON 作为数据存储和消息传输的编码格式。基于原始的 JSON 数据类型之上, BSON 提供了自己的扩展。BSON 具有 轻量级、易于遍历、更高效的特点。
BSON-数据类型
类型 | 编号 | 名称 | 描述 |
---|---|---|---|
Double | 1 | 双精度浮点 数 | 用于存储浮点值 |
String | 2 | 字符串 | MongoDB中的字符串必须为UTF_8编 码 |
Object | 3 | 对象 | 用于嵌入式文档 |
Array | 4 | 数组 | 用于将多个值存储到一个字段 多对多) (一对多、 |
Binary data | 5 | 二进制数据 | 用于存储二进制数据 |
ObjectId | 7 | 对象ID | 用于存储文档的ID |
Boolean | 8 | 布尔类型 | 用于存储布尔值(true / false)值 |
Date | 9 | 日期 | 用于以UNIX时间格式存储当前日期或 时间 |
Null | 10 | Null | 用于存储Null值 |
类型 | 编号 | 名称 | 描述 |
---|---|---|---|
Regular Expression | 11 | 正则表达式 | 用于正则匹配 |
JavaScript | 13 | Javascript | JS函数 |
JavaScript with scope | 15 | Javascript | 带闭包的JS函数 |
Integer | 16 and 18 | 整型 | 用于存储整数值,可以是32位或64位 |
timestamp | 17 | 时间戳 | 时间+计数器,作为oplog的关键字段 |
Decimal12 8 | 19 | 高精度浮点 数 | 用于存储高精度浮点值 |
Min key | -1 | 最小键 | 用于BSON元素比较 |
Max key | 127 | 最大键 | 用于BSON元素比较 |
BSON-ObjecteID
MongoDB 所有的文档都有一个唯一的_id字段,作为集合的主键。缺省情况下, MongoDB 使用 ObjectId 作为 _id 字段的类型。
ObjectId 共为 12 字节,包含时间戳、随机值和计数器几个部分。具体的生成方式由具体驱动实现。
- 前 4 个字节表示创建 unix 时间戳,格林尼治时间 UTC 时间,比北京时间晚了 8 个小时
- 接下来的 3 个字节是机器标识码
- 紧接的两个字节由进程 id 组成 PID
- 最后三个字节是计数器(初始值随机)
MongoDB 中存储的文档必须有一个 _id 键。这个键的值可以是任何类型的,默认是个 ObjectId 对象
由于 ObjectId 中保存了创建的时间戳,所以你不需要为你的文档保存时间戳字段,你可以通过 getTimestamp 函数来获取文档的创建时间:
> var newObject = ObjectId()
> newObject.getTimestamp()
ISODate("2022-03-24T15:02:48Z")
>
ObjectId 转为字符串
> newObject.str
623c88180ff770f03ea2cb6e
>
字符串
BSON 字符串都是 UTF-8 编码。
时间戳
BSON 有一个特殊的时间戳类型用于 MongoDB 内部使用,与普通的 日期 类型不相关。 时间戳值是一个 64 位的值。其中:
- 前32位是一个 time_t 值(与Unix新纪元相差的秒数)
- 后32位是在某秒中操作的一个递增的
序数
在单个 mongod 实例中,时间戳值通常是唯一的。
在复制集中, oplog 有一个 ts 字段。这个字段中的值使用BSON时间戳表示了操作时间。
BSON 时间戳类型主要用于 MongoDB 内部使用。在大多数情况下的应用开发中,你可以使用 BSON 日期类型。
BSON-Date
- Date 为日期类型,使用 64位长整数表示,等同于从 Unix epoch time 至今的毫秒值(当前距离 Unix新纪元(1970年1月1日)的毫秒数)。负数表示 1970 年之前的日期。
- MongoDB 采用 UTC 时区存储日期。
操作方法 | 说明 |
---|---|
Date() | 返回当前日期的字符串形式 |
New Date() | 返回 ISODate 日期对象 |
ISODate() | 返回 ISODate 日期对象 |
> var mydate1 = new Date() //格林尼治时间
> mydate1
ISODate("2022-03-24T15:07:44.239Z")
> typeof mydate1
object
> var mydate2 = ISODate() //格林尼治时间
> mydate2
ISODate("2022-03-24T15:08:07.447Z")
> typeof mydate2
object
>
这样创建的时间是日期类型,可以使用 JS 中的 Date 类型的方法。
返回一个时间类型的字符串:
> var mydate1str = mydate1.toString()
> mydate1str
Thu Mar 24 2022 23:07:44 GMT+0800 (CST)
> typeof mydate1str
string
或者
> Date()
Thu Mar 24 2022 23:09:37 GMT+0800 (CST)
资源:
英文官方参考文档: https://docs.mongodb.com/manual/reference/
中文社区参考文档: https://docs.mongoing.com/
中文社区: https://mongoing.com/
博客参考: https://mongoing.com/guoyuanwei
中文社区公众号: https://mp.weixin.qq.com/s/Wuzh47jsBh5QonBrZxUnjg 《WiredTiger 存储引擎系列》