一、MongoDB概述
MongoDB 是一个基于 分布式文件存储 的开源 NoSQL 数据库系统,由 C++ 编写的。MongoDB 提供了 面向文档 的存储方式,操作起来比较简单和容易,支持“无模式”的数据建模,可以存储比较复杂的数据类型,是一款非常流行的 文档类型数据库 。
在高负载的情况下,MongoDB 天然支持水平扩展和高可用,可以很方便地添加更多的节点/实例,以保证服务性能和可用性。在许多场景下,MongoDB 可以用于代替传统的关系型数据库或键/值存储方式,皆在为 Web 应用提供可扩展的高可用高性能数据存储解决方案
1、MongoDB的数据结构
MongoDB是面向文档的NoSQL(非关系型)数据库,它的数据结构由字段(Field)和值(Value)组成,类似于JSON对象:
{
name:"张三",
sex:"男性",
age:30
}
2、MongoDB的存储结构
MongoDB的存储结构区别于传统的关系型数据库,由如下三个单元组成:
-
文档(Document):MongoDB中最基本的单元,由BSON键值对(key-value)组成。相当于关系型数据库中的行(Row)。
-
集合(Collection):一个集合可以包含多个文档,相当于关系型数据库中的表格(Table)。
-
数据库(Database):等同于关系型数据库中的数据库概念,一个数据库中可以包含多个集合。您可以在MongoDB中创建多个数据库。
SQL 与 MongoDB 常见术语对比 :
SQL | MongoDB |
---|---|
表(Table) | 集合(Collection) |
行(Row) | 文档(Document) |
列(Col) | 字段(Field) |
主键(Primary Key) | 对象 ID(Objectid) |
索引(Index) | 索引(Index) |
嵌套表(Embeded Table) | 嵌入式文档(Embeded Document) |
数组(Array) | 数组(Array) |
二、Databases and Collections
1、概述
MongoDB将数据记录存储为文档(特别是BSON文档),这些文档在集合中聚集在一起。数据库存储一个或多个文档集合。
2、Databases
在MongoDB中,数据库保存一个或多个文档集合。要选择要使用的数据库,请在mongosh中使用use<db>语句,如下例所示:
use myDB
3、Create a Database
如果数据库不存在,MongoDB将在您首次存储该数据库的数据时创建该数据库。因此,您可以切换到不存在的数据库,并在mongosh中执行以下操作:
use myNewDB
db.myNewCollection1.insertOne( { x: 1 } )
insertOne()操作创建数据库myNewDB和集合myNewCollection1(如果它们不存在)。确保数据库和集合名称都遵循MongoDB命名限制。
3、Collections
MongoDB将文档存储在集合中。集合类似于关系数据库中的表。
4、Create a Collection
如果集合不存在,MongoDB会在您首次存储该集合的数据时创建该集合。
db.myNewCollection2.insertOne( { x: 1 } )
db.myNewCollection3.createIndex( { y: 1 } )
insertOne()和createIndex()操作都会创建各自的集合(如果它们不存在)。确保集合名称遵循MongoDB命名限制。
5、显式创建
MongoDB提供了db.createCollection()方法来显式创建具有各种选项的集合,例如设置最大大小或文档验证规则。如果没有指定这些选项,则不需要显式创建集合,因为MongoDB在首次存储集合的数据时会创建新的集合。
6、Document 验证
默认情况下,集合不要求其文档具有相同的架构;即,单个集合中的文档不需要具有相同的字段集,并且字段的数据类型可以在集合中的各个文档中不同。
然而,从MongoDB3.2开始,您可以在更新和插入操作期间强制集合的文档验证规则。
7、唯一标识符
集合被分配一个不可变的UUID。在副本集的所有成员和碎片集群中的碎片之间,集合UUID保持不变。
要检索集合的UUID,请运行listCollections命令或db.getCollectionInfos()方法。
三、Documents
MongoDB将数据记录存储为BSON文档。BSON是JSON文档的二进制表示,尽管它包含的数据类型比JSON多。有关BSON规范,请参阅bsonspec.org。另请参阅BSON类型。
1、兼容性
MongoDB将记录存储为在以下环境中托管的部署的文档:
- MongoDB Atlas:云中MongoDB部署的完全托管服务
- MongoDB Enterprise:MongoDB的基于订阅的自我管理版本
- MongoDB社区:MongoDB的源代码可用、免费使用和自我管理版本
2、Document 结构
MongoDB文档由字段和值对组成,结构如下:
{
field1: value1,
field2: value2,
field3: value3,
...
fieldN: valueN
}
字段的值可以是任何BSON数据类型,包括其他文档、数组和文档数组。例如,以下文档包含各种类型的值:
var mydoc = {
_id: ObjectId("5099803df3f4948bd2f98391"),
name: { first: "Alan", last: "Turing" },
birth: new Date('Jun 23, 1912'),
death: new Date('Jun 07, 1954'),
contribs: [ "Turing machine", "Turing test", "Turingery" ],
views : NumberLong(1250000)
}
上述字段具有以下数据类型:
- _id包含ObjectId。
- name保存一个嵌入的文档,其中包含第一个和最后一个字段。
birth
anddeath
保留Date类型的值。- contribs保存字符串数组。
views
保存NumberLong类型的值。
3、字段名称
字段名称是字符串。
文档对字段名有以下限制:
- 字段名_id保留为主键;它的值在集合中必须唯一,不可变,并且可以是数组以外的任何类型。如果_id包含子字段,则子字段名称不能以($)符号开头。
- 字段名不能包含空字符。
- 服务器允许存储包含点(.)和美元符号($)的字段名。
- MongodB 5.0增加了对在字段名中使用($)和(.)的改进支持。有一些限制。有关更多详细信息,请参阅字段名称注意事项。
BSON文档可以有多个同名字段。然而,大多数MongoDB接口使用不支持重复字段名的结构(例如哈希表)来表示MongoDB。如果需要处理具有多个同名字段的文档,请参阅驱动程序的驱动程序文档。
一些由内部MongoDB进程创建的文档可能具有重复的字段,但任何MongoDB流程都不会向现有用户文档添加重复的字段。
4、Arrays
要通过从零开始的索引位置指定或访问数组的元素,请将数组名称与点(.)和从零开始索引位置连接起来,并用引号括起来:
"<array>.<index>"
例如,给定文档中的以下字段:
{
...
contribs: [ "Turing machine", "Turing test", "Turingery" ],
...
}
5、嵌入式Document
要使用点表示法指定或访问嵌入文档的字段,请将嵌入文档名称与点(.)和字段名称连接起来,并用引号括起来:
"<embedded document>.<field>"
例如,给定文档中的以下字段:
{
...
name: { first: "Alan", last: "Turing" },
contact: { phone: { type: "cell", number: "111-222-3333" } },
...
}
- 要在名称字段中指定名为last的字段,请使用点符号“name.last”。
- 要在联系人字段中指定电话文档中的号码,请使用点符号“contact.phone.number”。
6、Document 限制
Document 具有以下属性:
文档大小限制
最大BSON文档大小为16 MB。
最大文档大小有助于确保单个文档不能使用过多的RAM,或者在传输期间不能使用过大的带宽。为了存储大于最大大小的文档,MongoDB提供了GridFS API。有关GridFS的更多信息,请参阅mongofiles和驱动程序的文档。
7、文档字段顺序
与JavaScript对象不同,BSON文档中的字段是有序的。
查询中的字段顺序
-
在比较文档时,字段顺序很重要。例如,当将文档与查询中的字段a和b进行比较时:
-
{a: 1, b: 1}
等于{a: 1, b: 1}
-
{a: 1, b: 1}
不等于{b: 1, a: 1}
-
- 为了有效地执行查询,查询引擎可以在查询处理期间对字段重新排序。在其他情况下,处理这些投影操作符时可能会重新排序字段:$project、$addFields、$set和$unset。
-
字段重新排序可能发生在中间结果以及 查询返回的最终结果。
-
由于某些操作可能会对字段重新排序,因此不应依赖 查询返回的结果中的特定字段排序 使用前面列出的投影运算符。
-
写入操作中的字段顺序
对于写入操作,MongoDB保留文档字段的顺序,但以下情况除外:
- _id字段始终是文档中的第一个字段。
- 包括重命名字段名的更新可能会导致文档中字段的重新排序。
8、_id字段
在MongoDB中,存储在集合中的每个文档都需要一个唯一的_id字段,该字段充当主键。如果插入的文档省略了_id字段,MongoDB驱动程序将自动为_id字段生成ObjectId。
这也适用于通过upsert:true的更新操作插入的文档。
_Iid字段具有以下行为和约束:
- 默认情况下,MongoDB在创建集合期间在_id字段上创建唯一索引。
- _id字段始终是文档中的第一个字段。如果服务器首先接收到一个没有_id字段的文档,那么服务器将把字段移到开头。
以下是存储_id值的常用选项:
- 使用ObjectId。
- 使用自然唯一标识符(如果可用)。这节省了空间,并避免了额外的索引。
- 生成自动递增的数字。
- 在应用程序代码中生成UUID。为了更有效地存储集合和_id索引中的UUID值,请将UUID存储为BSON BinData类型的值。
- 在以下情况下,BinData类型的索引键将更有效地存储在索引中:
-
二进制子类型值在 0-7 或 128-135 范围内,并且
-
字节数组的长度为:0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14、16、20、24 或 32。
-
- 使用驱动程序的BSON UUID工具生成UUID。请注意,驱动程序实现可能以不同的方式实现UUID序列化和反序列化逻辑,这可能与其他驱动程序不完全兼容。查看您的有关UUID互操作性的信息的驱动程序文档。