MongoDB数据类型详解

news2024/11/15 8:36:11

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.coloradmin.cn/o/1360697.html

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

相关文章

日程安排小程序实战教程

日常中我们经常有一些事情需要提醒自己&#xff0c;使用日历的形式比较符合实际的使用习惯。本篇我们就利用微搭低代码工具带着大家开发一款日程安排的小程序。 1 创建数据源 登录微搭低代码控制台&#xff0c;打开数据模型&#xff0c;点击创建 输入数据源的名称日程安排 …

vue封装组件(一)标签和下拉框组合实现添加数据

背景: 最近接入短剧内容&#xff0c;需要添加短剧合作方。在详情页需要支持添加组件 方案一&#xff1a;标签tag加上输入框实现添加数据。图片见下 这个是刚开始做的&#xff0c;后来产品觉得这样会造成随意修改数据&#xff0c;需要改成下拉框形式添加 方案二&#xff1a;标签…

【人工智能】深入了解人工智能的核心算法与应用实践

人工智能 学习AI要看的第一本书人工智能应当以人为本人工智能&#xff08;第3版&#xff09;通晓六点&#xff0c;明白人工智能是怎么回事基本概念和历史基础知识基于知识的系统高级专题现在和未来安全和编程 人工智能已经是基础学科 学习AI要看的第一本书 人工智能知识对于当…

PLC分段传送带控制示例

一、为了节约用电&#xff0c;将长长的传送带进行分段&#xff0c;哪断上有物品&#xff0c;哪断才运行 二、每一断末尾都有传感器&#xff0c;传感器能感受到物体有没有到传送带的末尾 三、这个传感器是接近开关 四、控制流程 五、IO地址分配 六、按下启动按钮后&#xff0c;…

【Linux软件包管理器】yum详解

目录 1、什么是软件包 2、yum的操作 1&#xff09;yum源 2&#xff09;三板斧 ① yum list ② yum install [软键名] ③ yum remove [软件名] 1、什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序. 但是这样太麻烦了,…

自存react crash course(1)

1.创建一个react 项目 确保有node.js 创建名为react-task-tracker的react项目 npx create-react-app react-task-tracker 启动项目 npm start2.项目结构 所有组件都是放在src下面的 3. jsx // jsx语法 和html很像&#xff0c;class用的是className来使用css的样式<div…

【unity】Obi插件架构组成(参数详细解释)——解算器四面板设置、三种更新器、参与者介绍

文章目录 一、架构&#xff08;Architecture&#xff09;1.1 Obi解算器&#xff08;ObiSolver&#xff09;1.2 ObiUpdater1.3 ObiActorBlueprint1.4 Obi参与者&#xff08;ObiActor&#xff0c;如ObiRope等&#xff09; 二、Obi解算器&#xff08;ObiSolver&#xff09;2.1 解算…

vue3学习 【2】vite起步和开发工具基本配置

vite的简介 官方文档 刚起步学习&#xff0c;所以我们只需要按照官方文档的入门流程即可。推荐阅读一下官网的为什么使用vite vite目前需要的node版本是18&#xff0c;可以参考上一篇文章的安装nvm&#xff0c;用来进行多版本的node管理。 vite安装与使用 npm create vitela…

24年初级会计资格考试报名信息采集流程共10大步骤,千万不要搞错

2024年初级会计资格考试报名信息采集流程共10大步骤&#xff0c;不要搞错哦&#xff1b; 第一步&#xff1a;输入证件号、点击登录 第二步&#xff1a;阅读采集须知 第三步&#xff1a;填写个人信息&#xff08;支付宝搜索"亿鸣证件照"或者微信搜索"随时照&q…

C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片

目录 效果 生成图片特征 查找踢足球的人 测试图片 模型信息 image_model.onnx text_model.onnx 项目 代码 Form1.cs Clip.cs 下载 C# Onnx Chinese CLIP 通过一句话从图库中搜出来符合要求的图片 效果 生成图片特征 查找踢足球的人 测试图片 模型信息 image_mod…

Java/JDK下载安装与环境配置

Java由Sun Microsystems&#xff08;现在是Oracle的子公司&#xff09;于1995年首次发布。它是一种面向对象的编程语言&#xff0c;广泛应用于Web开发、移动应用程序开发、桌面应用程序开发和企业级应用程序开发等领域。 Java语言的主要特点是跨平台、可移植性强、安全性高和具…

【AI视野·今日Sound 声学论文速览 第三十九期】Tue, 2 Jan 2024

AI视野今日CS.Sound 声学论文速览 Tue, 2 Jan 2024 Totally 7 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Enhancing Pre-trained ASR System Fine-tuning for Dysarthric Speech Recognition using Adversarial Data Augmentation Authors Huimen…

《微机原理与应用》期末考试题库(附答案解析)

第1章 微型计算机概述 1.微型计算机的硬件系统包括___A _____。 A&#xff0e;控制器、运算器、存储器和输入输出设备 B&#xff0e;控制器、主机、键盘和显示器 C&#xff0e;主机、电源、CPU和输入输出 D&#xff0e;CPU、键盘、显示器和打印机 2.微处…

LLM Agent零微调范式 ReAct Self Ask

前三章我们分别介绍了思维链的使用&#xff0c;原理和在小模型上的使用。这一章我们正式进入应用层面&#xff0c;聊聊如何把思维链和工具使用结合得到人工智能代理。 要回答我们为什么需要AI代理&#xff1f;代理可以解决哪些问题&#xff1f;可以有以下两个视角 首先是我们…

算法训练day60|单调栈part0

参考&#xff1a;代码随想录 84.柱状图中最大的矩形 要求当前柱形的左右两边第一个比他小的位置 对于高度为5的柱子&#xff08;index为2&#xff09; mid 他的左边第一个比他小的柱子为1&#xff0c;index为1 left 他的右边第一个比他小的柱子高度为2&#xff0c;index为4…

Springcloud 微服务实战笔记 Eureka

服务治理 服务注册 在服务治理框架中&#xff0c;通常都会构建一个注册中心&#xff0c;每个服务单元向注册中心登记自己提供的服务&#xff0c;将主机与端口号、版本号、通信协议等一些附加信息告知注册中心&#xff0c;注册中心按服务名分类组织服务清单。当服务启动后&…

DBeaver 连接mysql 报错 Public Key Retrieval is not allowed

问题描述 一段时间没有用本地数据库&#xff0c;使用dbeaver连接mysql报错&#xff1a;Public Key Retrieval is not allowed 原因分析&#xff1a; Public Key Retrieval is not allowed&#xff1a;不允许进行公钥检索。 解决方案&#xff1a; 在编辑连接中找到allowPu…

swift ——多行文字前面内容省略

首先来说一说ios中的 lineBreakModelineBreakMode : 设置文字过长时的显示截断样式 可选值如下 byWordWrapping &#xff1a; 以单词为单位换行&#xff0c;以单词为单位截断。byCharWrapping &#xff1a;以字符为单位换行&#xff0c;以字符为单位截断。byClipping &#x…

Note: A Journey Across Canada

A Journey Across Canada 一场横穿加拿大的旅行 across journey After a quiz last autumn, Kuang crossed the continent eastward to Toronto to visit his schoolmate, the distance measuring approximately 5000 kilometers. 去年秋天一次考试后&#xff0c;Kuang向东穿…

计算机毕业设计 基于SpringBoot的公司资产网站的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…