MongoDB简单介绍
近来工作需要用mongo,之前一直是用的mysql数据库,所以学一下有关mongo的基础,顺便水一篇博客,不出意外的话可以水三篇,一篇基础介绍,一篇sql语法,一篇java连接及使用,如果比较闲的话可能会像mysql一样补一个底层架构或者集群(单机、主从、主备、分片、混合)部署
MongoDB是一个基于「分布式文件存储」的数据库,它属于NoSQL数据库,由C++语言编写,旨在为WEB应用提供「可扩展」的「高性能」数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库中最丰富,最像关系数据库的,它支持的数据结构非常松散,类似json的bson(二进制json)格式,因此可以存储比较复杂的数据类型,MongoDB最大的特点是它支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库表查询的绝大部分功能,而且还支持对数据建立索引,它在某些方面可以替代MySQL,比如,MongoDB拥有数据的引用,排序,分页,聚合(分)等操作
Docker环境下MongoDB的安装
按流程来说,这里应该是一些术语和概念描述了,但是,你都没有mongo数据库我给你讲术语你又看不到,所以这里插一条mongo数据库的安装,有关docker的安装可以看我之前的文章
## 先看看都有哪些可用的镜像
$ docker search mongo
## 然后挑一下你喜欢的镜像拉下来💩
$ docker pull mongo
## 拉好后回头看看它什么样
$ docker images
## 然后把他run起来,这里就不挂存储卷了,如果你想挂载用 “-v”
$ docker run -d -p 27017:27017 --name mongo docker.io/mongo
## 然后我们看看这个容器它的状态,你会看到他的状态是 Up About a minute,就很好,还是热乎的
$ docker ps
## 然后,没有然后了,你可以通过你的数据库连接工具连接你的mongo了,至于身份认证权限什么,自己百度去
MongoDB概念/术语的解析
| SQL | MongoDB | 解释/说明 |
|---|---|---|
| database | database | 数据库 |
| table | collection | 数据库表/集合 |
| row | document | 数据记录行/文档 |
| column | field | 数据字段/域 |
| Index | index | 索引 |
| primary key | primary key | 主键/mongo目前将_id设置为主键 |
| table joins | 表连接 - mongo不支持 |
- 数据库
mongo的单个实例可以容纳多个独立的数据库,每一个都有自己的集合和权限,不同的数据库也放置在不同的文件中,默认数据库为db,该数据库存储在data目录中(安装时可以默认,可以指定,但该目录必须存在)
有一些数据库名是保留的,可以直接访问这些有特殊作用的数据库
- admin: 从权限角度来看,这是"root"数据库,要是将一个用户添加到这个数据库,这个用户自动继承所有数据库的权限,一些特定的服务器端命令也只能从这个数据库运行. e.g: 列出所有数据库或关闭服务器
- local: 这个数据永远不会被复制,可以用来存储于本地单台服务器的任意集合
- config: 当mongo用于分片设置时,config数据库在内部使用,用来保存分片的相关信息
- 文档
文档是一组键值(key-value)对,MongoDB的文档不需要设置相同的字段,并且相同的字段不需要相同的数据类型,这与关系型数据库有很大的区别,也是MongoDB非常突出的特点
需要注意的是:
- 文档中的键/值对是有序的.
- 文档中的值不仅可以使在双引号里的字符串,还可以使其他几种数据类型,甚至可以是嵌入的文档.
- MongoDB区分类型和大小写
- MongoDB的文档不能有重复的键.
- 文档的键是字符串,处了少数例外情况,键可以是任意UTF-8字符
文档键命名规范:
- 键不能含有\0(空字符),这个字符用来表示键的结尾.
- "." 和 "$"有特别的意义,只有在特定环境下才能使用.
- 以下划线"_"开头的键是保留的(非严格要求)
- 集合
集合就是mongo的文档组,类似于RDBMS(关系数据库管理系统: Relation Database Management System)中的表格,集合存在于数据库中,集合没有固定的结构,这意味着你在对集合可以插入不同格式和类型的数据,但通常情况下我们插入集合的数据都会有一定的关联性.
当第一个文档插入时,集合就会被创建,一个collection(集合)中的所有field(域)是collection(集合)中所有document(文档)中包含的filed(域)的并集
合法的集合名:
- 集合名不能是空字符串“”.
- 集合名不能还有\0字符,这个字符表示集合名的结尾.
- 集合名不能以"system."开头,这是为系统集合保留的前缀.
- 用户创建的集合名字不能含有保留字符,不要在名字里出现"$".
Capped Collection
Capped collection 就是固定大小的collection, 它有很高的性能以及队列过期的特性(过期按照插入的顺序).和"RRD(Round Robin Database)"概念类似,它自动的维护对象的插入顺序,非常适合类似记录日志的功能,和标准的collection不同,必须要显式的创建,指定collection的大小,单位是字节(指定的存储大小包含了数据库头的信息),collection的数据存储空间是提前分配的, Capped collection是按照文档的插入顺序保存到集合中的,而这些文档在磁盘上的存储位置也是按照插入顺序来保存的,当更新Capped collection中文档的时候,更新后的文档不可以超过之前文档的大小,这样可以确保所有文档在磁盘上的位置一直保持不变
ps. MongoDB的操作日志文件oplog.rs就是利用Capped collection实现的
db.createCollection("operate_log", {capped: true, size: 100000})
- 在 Capped collection中,你能添加新的对象
- 能进行更新,并且对象不会增加存储空间,如果造成了存储空间增加(超出原定大小),更新就会失败
- 使用Capped 不能删除一个文档,可以使用
drop()删除collection中所有的field - 在32bit机器中,Capped的最大存储为
1 * 10^9个字节
- 元数据
元数据是一个预留空间,在对数据库或应用程序结构执行修改时,其内容可以由数据库自动更新。元数据是系统中各类数据描述的集合,是执行详细的数据收集和数据分析的主要途径。 元数据最重要的作用是作为分析阶段的工具。任何字典最重要的用途都是查询,在结构化分析中,元数据的作用是给数据流图上的每个节点加以定义和说明。换句话说,数据流图上的所有节点的定义和解释的集合就是元数据,而且在元数据中建立严密一致的定义有助于提高需求分析人员和用户沟通的效率。
ps. 从别人那粘过来的,我也不知道啥意思,没用到元数据
MongoDB数据类型
| 数据类型 | 说明 | 解释 | e.g | |
|---|---|---|---|---|
| String | 字符串 | UTF-8编码的字符串才是合法的 | {"v": "demo"} | |
| Integer | 整型数值 | 可分为32位和64位 | {"v": 112} | |
| Boolean | 布尔值 | 用于存储布尔值(true | false) | {"v": true} |
| Double | 双精度浮点值 | 用于存储浮点值 | {"v": 3,14} | |
| ObjectID | 对象ID | 用于创建文档的ID | {"_id": ObjectId("1123")} | |
| Array | 数组 | 用于将数组或列表或多个值存储为一个键 | {"arr": ["1","213","as"]} | |
| Timestamp | 时间戳 | 从开始纪元开始的毫秒数 | {"ts": 1646897955411} | |
| Object | 内嵌文档 | 文档可以作为文档中某个key的value | {"o": {"foo": "bar"}} | |
| Null | 空值 | 表示空值或为定义的对象 | {"v": null} | |
| Date | 日期 | 日期时间,用Unix日期格式来存储当前日期或时间 | {"date": new Date()} | |
| Regular | 正则表达式 | 文档中可以包含正则表达式,遵循JS语法 | {"v": /^d/} | |
| Code | 代码 | 可以包含JS代码 | {"fn": function(){}} | |
| File | 文件 | 二进制转码(base64)后存储(< 16M) | GridFS( > 16M) | GridFS用两个集合来存储一个文件: fs.files\ f.schunks |
- 不得不说的ObjectId
ObjectId类似唯一主键,可以很快的生成和排序,包含12bytes,其含义有:
-
前4个字节表示创建unix时间戳,格林尼治(UTC)时间
-
接下来三个字节是极其标识码
-
紧接的两个字节由进程id组成PID
-
最后三个字节是随机数
MongoDB中存储的文档必须有一个_id键,这个键可以是任何类型的,默认是个ObjectId对象
由于ObjectId中保存了创建的时间戳,所以不需要为文档特意去保存时间戳字段,完全可以通过getTimestamp函数来获取文档的创建时间
> var newObject = objectId()
> newObject.getTimestamp()
ObjectId还可以转为字符串
> newObject.str