MongoDB数据类型详解

BSON 协议与数据类型

MongoDB 为什么会使用 BSON?

JSON 是当今非常通用的一种跨语言 Web 数据交互格式,属 ECMAScript 标准规范的一个子集。JSON (JavaScript Object Notation,JS 对象简谱)即 JavaScript 对象表示法,它是 JavaScript 对象的一种文本表现形式。
作为一种轻量级的数据交换格式,JSON 的可读性非常好,而且非常便于系统生成和解析,这些优势也让它逐渐取代了 XML 标准在 Web 领域的地位,当今许多流行的 Web 应用开发框架,如 SpringBoot 都选择了 JSON 作为默认的数据编/解码格式。
JSON 只定义了 6 种数据类型:

  • string: 字符串
  • number : 数值
  • object: JS 的对象形式,用 {key:value} 表示,可嵌套
  • array: 数组,JS 的表示方式 [value],可嵌套
  • true/false: 布尔类型
  • null: 空值

大多数情况下,使用 JSON 作为数据交互格式已经是理想的选择,但是 JSON 基于文本的解析效率并不是最好的,在某些场景下往往会考虑选择更合适的编/解码格式,一些做法如:

  • 在微服务架构中,使用 gRPC(基于 Google 的 Protobuf)可以获得更好的网络利用率。
  • 分布式中间件、数据库,使用私有定制的 TCP 数据包格式来提供高性能、低延时的计算能力。

BSON 由 10gen 团队设计并开源,目前主要用于 MongoDB 数据库。BSON(Binary JSON)是二进制版本的 JSON,其在性能方面有更优的表现。BSON 在许多方面和 JSON 保持一致,其同样也支持内嵌的文档对象和数组结构。二者最大的区别在于 JSON 是基于文本的,而 BSON 则是二进制(字节流)编/解码的形式。在空间的使用上,BSON 相比 JSON 并没有明显的优势。
MongoDB 在文档存储、命令协议上都采用了 BSON 作为编/解码格式,主要具有如下优势:

  • 类 JSON 的轻量级语义,支持简单清晰的嵌套、数组层次结构,可以实现模式灵活的文档结构。
  • 更高效的遍历,BSON 在编码时会记录每个元素的长度,可以直接通过 seek 操作进行元素的内容读取,相对 JSON 解析来说,遍历速度更快。
  • 更丰富的数据类型,除了 JSON 的基本数据类型,BSON 还提供了 MongoDB 所需的一些扩展类型,比如日期、二进制数据等,这更加方便数据的表示和操作。

BSON 的数据类型

MongoDB 中,一个 BSON 文档最大大小为 16M,文档嵌套的级别不超过100。

https://www.mongodb.com/docs/v6.0/reference/bson-types/

TypeNumberAliasNotes
Double1“double”
String2“string”
Object3“object”
Array4“array”
Binary data5“binData”二进制数据
Undefined6“undefined”Deprecated.
ObjectId7“objectId”对象ID,用于创建文档ID
Boolean8“bool”
Date9“date”
Null10“null”
Regular Expression11“regex”正则表达式
DBPointer12“dbPointer”Deprecated.
JavaScript13“javascript”
Symbol14“symbol”Deprecated.
JavaScript code with scope15“javascriptWithScope”Deprecated in MongoDB 4.4.
32-bit integer16“int”
Timestamp17“timestamp”
64-bit integer18“long”
Decimal12819“decimal”New in version 3.4.
Min key-1“minKey”表示一个最小值
Max key127“maxKey”表示一个最大值

t y p e 操作符: < b r / > type 操作符:<br /> type操作符:<br/>type 操作符基于 BSON 类型来检索集合中匹配的数据类型,并返回结果。

db.books.find({"title" : {$type : 2}})
// 或者
db.books.find({"title" : {$type : "string"}})

日期类型

MongoDB 的日期类型使用 UTC(Coordinated Universal Time,即世界协调时)进行存储,也就是 +0 时区的时间。

db.dates.insertMany([{data1:Date()},{data2:new Date()},{data3:ISODate()}])
db.dates.find().pretty()

使用 new Date 与 ISODate 最终都会生成 ISODate 类型的字段(对应于 UTC 时间)。

ObjectId 生成器

MongoDB 集合中所有的文档都有一个唯一的 _id 字段,作为集合的主键。在默认情况下,_id 字段使用 ObjectId 类型,采用 16 进制编码形式,共 12 个字节。
image.png
为了避免文档的 _id 字段出现重复,ObjectId 被定义为 3 个部分:

  • 4 字节表示 Unix 时间戳(秒)。
  • 5 字节表示随机数(机器号+进程号唯一)。
  • 3 字节表示计数器(初始化时随机)。

大多数客户端驱动都会自行生成这个字段,比如 MongoDB Java Driver 会根据插入的文档是否包含 _id 字段来自动补充 ObjectId 对象。这样做不但提高了离散性,还可以降低 MongoDB 服务器端的计算压力。在 ObjectId 的组成中,5 字节的随机数并没有明确定义,客户端可以采用机器号、进程号来实现:
image.png

属性/方法描述
str返回对象的十六进制字符串表示。
ObjectId.getTimestamp()将对象的时间戳部分作为日期返回。
ObjectId.toString()以字符串文字“”的形式返回 JavaScript 表示ObjectId(…)。
ObjectId.valueOf()将对象的表示形式返回为十六进制字符串。返回的字符串是 str 属性。

生成一个新的 ObjectId:

x = ObjectId()

内嵌文档和数组

内嵌文档

一个文档中可以包含作者的信息,包括作者名称、性别、家乡所在地,一个显著的优点是,当我们查询 book 文档的信息时,作者的信息也会一并返回。

db.books.insert({title: "撒哈拉的故事",author: {name:"三毛",gender:"女",hometown:"重庆"}
})

查询三毛的作品:

db.books.find({"author.name":"三毛"})

修改三毛的家乡所在地:

db.books.updateOne({"author.name":"三毛"},{$set:{"author.hometown":"重庆/台湾"}})

数组

除了作者信息,文档中还包含了若干个标签,这些标签可以用来表示文档所包含的一些特征,如豆瓣读书中的标签(tag)。
增加 tags 标签:

db.books.updateOne({"author.name":"三毛"},{$set:{tags:["旅行","随笔","散文","爱情","文学"]}})

查询数组元素:

# 会查询到所有的tags
db.books.find({"author.name":"三毛"},{title:1,tags:1})
# 利用$slice获取最后一个tag
db.books.find({"author.name":"三毛"},{title:1,tags:{$slice:-1}})

$silice 是一个查询操作符,用于指定数组的切片方式

数组末尾追加元素,可以使用 $push 操作符:

db.books.updateOne({"author.name":"三毛"},{$push:{tags:"猎奇"}})

$push 操作符可以配合其他操作符,一起实现不同的数组修改操作,比如和 $each 操作符配合可以用于添加多个元素:

db.books.updateOne({"author.name":"三毛"},{$push:{tags:{$each:["伤感","想象力"]}}})

如果加上 $slice 操作符,那么只会保留经过切片后的元素:

db.books.updateOne({"author.name":"三毛"},{$push:{tags:{$each:["伤感","想象力"],$slice:-3}}})

根据元素查询:

# 会查出所有包含伤感的文档
db.books.find({tags:"伤感"})
# 会查出所有同时包含"伤感","想象力"的文档
db.books.find({tags:{$all:["伤感","想象力"]}})

嵌套型的数组

数组元素可以是基本类型,也可以是内嵌的文档结构

{tags:[{tagKey:xxx,tagValue:xxxx},{tagKey:xxx,tagValue:xxxx}]
}

这种结构非常灵活,一个很适合的场景就是商品的多属性表示。

一个商品可以同时包含多个维度的属性,比如尺码、颜色、风格等,使用文档可以表示为:

db.goods.insertMany([{name:"羽绒服",tags:[{tagKey:"size",tagValue:["M","L","XL","XXL","XXXL"]},{tagKey:"color",tagValue:["黑色","宝蓝"]},{tagKey:"style",tagValue:"韩风"}]
},{name:"羊毛衫",tags:[{tagKey:"size",tagValue:["L","XL","XXL"]},{tagKey:"color",tagValue:["蓝色","杏色"]},{tagKey:"style",tagValue:"韩风"}]
}])

以上的设计是一种常见的多值属性的做法,当我们需要根据属性进行检索时,需要用到 $elementMatch 操作符:

# 筛选出color=黑色的商品信息
db.goods.find({tags:{$elemMatch:{tagKey:"color",tagValue:"黑色"}}
})

如果进行组合式的条件检索,则可以使用多个 $elemMatch 操作符:

# 筛选出color=蓝色,并且size=XL的商品信息
db.goods.find({tags:{$all:[{$elemMatch:{tagKey:"color",tagValue:"黑色"}},{$elemMatch:{tagKey:"size",tagValue:"XL"}}]  }
})

固定(封顶)集合

https://www.mongodb.com/docs/manual/core/capped-collections/

固定集合(capped collection)是一种限定大小的集合,其中 capped 是覆盖、限额的意思。跟普通的集合相比,数据在写入这种集合时遵循 FIFO 原则。可以将这种集合想象为一个环状的队列,新文档在写入时会被插入队列的末尾,如果队列已满,那么之前的文档就会被新写入的文档所覆盖。通过固定集合的大小,我们可以保证数据库只会存储“限额”的数据,超过该限额的旧数据都会被丢弃。
image.png

使用示例

创建固定集合:

db.createCollection("logs",{capped:true,size:4096,max:10})

max:指集合的文档数量最大值,这里是 10 条
size:指集合的空间占用最大值,这里是 4096 字节(4 KB)

这两个参数会同时对集合的上限产生影响。也就是说,只要任一条件达到阈值都会认为集合已经写满。其中 size 是必选的,而 max 则是可选的。
可以使用collection.stats命令查看文档的占用空间:

db.logs.stats()

image.png
将普通集合转换为固定集合:

db.runCommand({"convertToCapped": "mycoll", size: 100000})

测试:
尝试在这个集合中插入 15 条数据,再查询会发现,由于文档数量上限被设定为 10 条,前面插入的 5 条数据已经被覆盖了。

for(var i=0;i<15;i++){db.logs.insert({t:"row-"+i})
}

image.png

适用场景

固定集合很适合用来存储一些“临时态”的数据。“临时态”意味着数据在一定程度上可以被丢弃。同时,用户还应该更关注最新的数据,随着时间的推移,数据的重要性逐渐降低,直至被淘汰处理。
一些适用的场景如下:

  • 系统日志

这非常符合固定集合的特征,而日志系统通常也只需要一个固定的空间来存放日志。在 MongoDB 内部,副本集的同步日志(oplog)就使用了固定集合。

  • 存储少量文档

如最新发布的 TopN 条文章信息。得益于内部缓存的作用,对于这种少量文档的查询是非常高效的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/601737.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源项目 | 完整部署流程、一款开源人人可用的开源数据可视化分析工具

&#x1f4da; 项目介绍 在互联网数据大爆炸的这几年&#xff0c;各类数据处理、数据可视化的需求使得 GitHub 上诞生了一大批高质量的 BI 工具。 借助这些 BI 工具&#xff0c;我们能够大幅提升数据分析效率、生成更高质量的项目报告&#xff0c;让用户通过直观的数据看到结…

微服务实战系列之API加密

前言 随着一阵阵凛冽寒风的呼啸&#xff0c;新的年轮不知不觉滚滚而来。故事随着2023的远去&#xff0c;尘封于案底&#xff1b;希望迎着新年&#xff0c;绽放于枝头。在2024新岁启航&#xff0c;扬帆破浪之时&#xff0c;让烦恼抛洒于九霄&#xff0c;让生机蓬勃于朝朝暮暮。 …

如何充值GPT会员账号?

详情点击链接&#xff1a;如何充值GPT会员账号&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二定制自己的…

基于多反应堆的高并发服务器【C/C++/Reactor】(中)创建并初始化TcpServer实例 以及 启动

对于一个TcpServer来说&#xff0c;它的灵魂是什么&#xff1f;就是需要提供一个事件循环EventLop(EventLoop)&#xff0c;不停地去检测有没有客户端的连接到达&#xff0c;有没有客户端给服务器发送数据&#xff0c;描述的这些动作&#xff0c;反应堆模型能够胜任。当服务器和…

【Docker】容器的相关命令

上一篇&#xff1a;创建&#xff0c;查看&#xff0c;进入容器 https://blog.csdn.net/m0_67930426/article/details/135430093?spm1001.2014.3001.5502 目录 1. 关闭容器 2.启动容器 3.删除容器 4.查看容器的信息 查看容器 1. 关闭容器 从图上来看&#xff0c;容器 aa…

机器学习-基于attention机制来实现对Image Caption图像描述实验

机器学习-基于attention机制来实现对Image Caption图像描述实验 实验目的 基于attention机制来实现对Image Caption图像描述 实验内容 1.了解一下RNN的Encoder-Decoder结构 在最原始的RNN结构中&#xff0c;输入序列和输出序列必须是严格等长的。但在机器翻译等任务中&…

idea中使用Lombok 失效,@Slf4j 找不到符号的解决办法

文章目录 一、前言二、问题排查和解决方案三、 其他解决方案3.1 另一种解决方案3.2 参考文章 一、前言 今天在一个多module工程中&#xff0c;新增了一个 springboot&#xff08;版本 2.2.4.RELEASE&#xff09; module&#xff0c;像往常一样&#xff0c;我引入了lombok依赖&…

selenium 用webdriver.Chrome 访问网页闪退解决方案

1.1.1. 解决方案&#xff1a; 1.1.1.1. 移动插件到谷歌的安装目录下 1.1.1.2. 设置环境变量 1.1.1.3. 重启电脑检查成功 解决时间&#xff1a;5min

58.网游逆向分析与插件开发-游戏增加自动化助手接口-游戏菜单文字资源读取的逆向分析

内容来源于&#xff1a;易道云信息技术研究院VIP课 之前的内容&#xff1a;接管游戏的自动药水设定功能-CSDN博客 码云地址&#xff08;master分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;34b9c1d43b512d0b4a3c395b…

Springboot支付宝沙箱支付(完整详细步骤)

Springboot支付宝沙箱支付&#xff08;完整详细步骤&#xff09; 网页操作步骤1.进入支付宝开发平台—沙箱环境2.点击沙箱进入沙箱环境3.进入沙箱&#xff0c;配置接口加签方式4.配置应用网关5.生成自己的密钥 IntelliJ IDEA 操作步骤1.导入依赖2.在 application.yml 里面进行配…

java基于SSM的毕业生就业管理系统+vue论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本毕业生就业管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信…

TypeScript接口、对象

目录 1、TypeScript 接口 1.1、实例 1.2、联合类型和接口 1.3、接口和数组 1.4、接口和继承 1.5、单继承实例 1.6、多继承实例 2、TypeScript 对象 2.2、对象实例 2.3、TypeScript类型模板 2.4、鸭子类型&#xff08;Duck typing&#xff09; 1、TypeScript 接口 接口…

Mac启动时候出现禁止符号

Mac启动时候出现禁止符号 启动时候出现禁止符号,意味着 选定的启动磁盘 包含 Mac 操作系统&#xff0c;但它不是 您的 Mac 可以使用的 macOS 。您应该在这个磁盘上 重新安装 macOS 。 可以尝试以下苹果提供的方法&#xff1a; Mac启动时候出现禁止符号 不要轻易抹除磁盘&am…

idea将本地编译好的代码上传到hub镜像仓库

第一步&#xff1a;编译打包本地的文件 package 第二步&#xff1a;执行docker bulid打包命令 docker build -t sunyuhua/algo-ability:1.0.0 .sunyuhuasunyuhua-HKF-WXX:~/workspace/shbgit/algo-ability$ docker build -t sunyuhua/algo-ability:1.0.0 . [] Building 141.…

C语言编译器(C语言编程软件)完全攻略

介绍常用C语言编译器的安装、配置和使用。 常用的C语言编译器&#xff08;编程软件&#xff09;介绍&#xff0c;同时附带下载地址、详细的安装教程和使用教程。我们还对比了不同C语言编译器&#xff08;C语言编程软件&#xff09;的优缺点&#xff0c;让初学者知道该如何选择…

差分电路原理以及为什么输出电压要偏移

我们在使用放大器芯片的时候&#xff0c;除了对放大器芯片本身应用外&#xff0c;通常还需要搭建一些外围电路来满足放大器芯片的使用条件&#xff0c;最终满足应用的功能&#xff0c;下面通过一个差分电路来熟悉这些应用。 差分运算放大电路&#xff0c;对共模信号得到有效抑…

C# Image Caption

目录 介绍 效果 模型 decoder_fc_nsc.onnx encoder.onnx 项目 代码 下载 C# Image Caption 介绍 地址&#xff1a;https://github.com/ruotianluo/ImageCaptioning.pytorch I decide to sync up this repo and self-critical.pytorch. (The old master is in old ma…

实战演练 | Navicat 中编辑器设置的配置

Navicat 是一款功能强大的数据库管理工具&#xff0c;为开发人员和数据库管理员提供稳健的环境。其中&#xff0c;一个重要功能是 SQL 编辑器&#xff0c;用户可以在 SQL 编辑器中编写和执行 SQL 查询。Navicat 的编辑器设置可让用户自定义编辑器环境&#xff0c;以满足特定的团…

ejs默认配置 造成原型链污染

文章目录 ejs默认配置 造成原型链污染漏洞背景漏洞分析漏洞利用 例题 [SEETF 2023]Express JavaScript Security ejs默认配置 造成原型链污染 参考文章 漏洞背景 EJS维护者对原型链污染的问题有着很好的理解&#xff0c;并使用非常安全的函数清理他们创建的每个对象 利用Re…

鸿蒙应用中的通知

目录 1、通知流程 2、发布通知 2.1、发布基础类型通知 2.1.1、接口说明 2.1.2、普通文本类型通知 2.1.3、长文本类型通知 2.1.4、多行文本类型通知 2.1.5、图片类型通知 2.2、发布进度条类型通知 2.2.1、接口说明 2.2.2、示例 2.3、为通知添加行为意图 2.3.1、接…