MongoDB 数据类型
目录
BSON 类型
二进制数据(Binary Data)
ObjectId
ObjectId定义
文档中的ObjectId
ObjectId的单调性
字符串(String)
时间戳(Timestamps)
日期(Date)
BSON类型的排序
数值类型的比较
字符串比较
数组的比较
对象的比较
日期和时间戳
不存在字段
二进制数据
Mongodb是文档型数据库,文档表示一条数据记录。文档由键值对构成。
//一个文档示例
{"key_1": value_1,"key_2": value_2...
}
其中,键值对中的键,或叫做字段名称,是由字符类型来定义的。而值的类型,是BSON类型中的某一个类型。
BSON 类型
BSON是一个二进制序列格式,用来保存文档,实现在mongodb中的远程调用。Mongodb支持不同的BSON类型,现在可用的BSON类型,其数字代码,字符识别码列在下表中。
| 类型 | 数字代码 | 别名 | 中文名 |
| Double | 1 | "double" | 浮点型 |
| String | 2 | "string" | 字符串 |
| Object | 3 | "object" | 对象 |
| Array | 4 | "array" | 数组 |
| Binary data | 5 | "binData" | 二进制数据 |
| ObjectId | 7 | "objectId" | 对象id |
| Boolean | 8 | "bool" | 布尔 |
| Date | 9 | "date" | 日期 |
| Null | 10 | "null" | 空值 |
| Regular Expression | 11 | "regex" | 正则表达式 |
| JavaScript | 13 | "javascript" | javascript脚本 |
| 32-bit Integer | 16 | "int" | 整型 |
| Timestamp | 17 | "timestamp" | 时间戳 |
| 64-bit Integer | 18 | "long" | 长整型 |
| Decimal128 | 19 | "decimal" | 小数 |
| Min Key | -1 | "minKey" | 最小值 |
| Max Key | 127 | "maxKey" | 最大值 |
在Mongodb中,可以使用数字代码和别名作为过滤条件查询文档。在聚合操作中,可以获取字段类型的别名。或者根据返回的字段类型实现不同的逻辑。
如查询字段类型是数组类型的数据
//使用字符串"array"和数字类型4查询字段类型是数组的数据
db.collection.find({<field_name>: {$type: "array"}})
db.collection.find({<field_name>: {$type: 4}})
二进制数据(Binary Data)
BSON的二进制数据由字节数组组成。每一个二进制数据也有一个标志解析二进制数据的子类型。下面表描述了子类型。
| 数字 | 子类型 |
| 0 | 通用二进制数据 |
| 1 | Function data |
| 2 | Binary(old) |
| 3 | UUID(old) |
| 4 | UUID |
| 5 | MD5加密 |
| 6 | 加密BSON数值 |
| 7 | 压缩时序数据 |
| 128 | 用户自定义 |
ObjectId
使用mongodb时 , 当集合中的文档没有_id字段时,会为文档自动生成一个ObjectId类型的_id。日常查询过程中,也能看到_id是ObjectId里带有一段字符串, 这个字符串代表什么意义,和其他类型的ID有什么相同或不同。本文研究mongodb官方文档,并通过实践来解释ObjectID这个数据类型。
ObjectId定义
ObjectId是一种小型的,几乎是唯一的,易于产生和排序的数据结构。长度是12个字节,由3部分组成
- 4个字节的时间戳,表明objectId的创建时间,以秒为单位的unix时间
- 5个字节的随机字符串,在运行机器上的进程中是唯一的
- 3个字节的增长计数器,初始值是一个随机数
其中时间戳和增长计数器与其他BSON类型不同,是按照高位优先排序。
如果使用数字类型来创建ObjectID, ObjectID中的时间戳,会被数字值来替代。
//使用数字类型定义3个ObjectID
db.inventory.insertMany([{part: 'AB307',_id: ObjectId(1)
},{part: 'AB307',_id: ObjectId(2)
},{part: 'AB307',_id: ObjectId(3)
}])// 产生的id中,数字类型替代了4个字节的时间戳
{"acknowledged" : true,"insertedId" : ObjectId("000000013e53cb5bc48f4e54")
}
{"acknowledged" : true,"insertedId" : ObjectId("000000023e53cb5bc48f4e55")
}
{"acknowledged" : true,"insertedId" : ObjectId("000000033e53cb5bc48f4e56")
}
上面代码的运行结果中可以看到,4个字节长度的00000001,00000002,00000003,替代了时间错。而后面3个字节长度的增长计数器,8f4e54,8f4e55,8f4e56在每一条新纪录插入时,都会增长。而中间3e53cb5bc4这个长度为5个字节的字符串,是由运行机器进程中随机产生的字符串。
时间戳+随机字符串+自增长字符串,保证了objectId的唯一性。
文档中的ObjectId
Mongodb的每一个文档都需要有唯一的_id字段作为主键。如果没有_id字段,mongodb自动添加一个ObjectId作为_id字段。这对于设置{upsert:true}的更新语句插入数据同样适用。
使用ObjectId作为_id字段的好处
- 在mongosh中,通过ObjectId.getTimestamp()方法,获取文档创建时间
//运行代码
ObjectId("655ef22e69185fac9ce3ce92").getTimestamp()
//获取创建时间
ISODate("2023-11-23T14:33:18.000+08:00")
- 按照_id排序,等价于按照文档创建时间排序
ObjectId的单调性
ObjectId虽然按照时间来产生,并带有随机数保证其唯一性。但objectId并不是单调的,受到两个因素影响
- 产生objectId仅仅以秒为单位,记录下来unix时间。当同一秒钟产生多个objectId时,并不能保证每一个objectid的排列顺序。
- 通过client产生的ObjectId, 其时间错可能与服务器时间不一致
字符串(String)
BSON类型的字符串是UTF-8格式的。各种语言连接mongodb时,通常都会使用UTF-8格式的字符串。这种格式保证了大部分语言的通用性。
时间戳(Timestamps)
BSON 的timestamps类型是一种内部使用的特殊格式。这种类型与常见的日期(Date)类型不同。timestamps类型是一个64位的数值
-
- 前面32位的unix时间,精确到秒
- 后32位的自增型操作数。表示在一秒内的操作数。
虽然BSON格式是小端序的,因此首先存储最低有效位,但在所有平台上,mongod实例总是在序数值之前比较time_t值,而不考虑端序。
在同一个mongodb运行实例中,timestamp值是唯一的。
在复制集中,oplog有一个时间类型的ts字段。这个字段使用timestamp类型表示操作时间。
当在文档中插入一个空的timestamp数值时,mongodb会将空的timestamp数字换成当前时间。但如果_id字段包含一个空的timestamp值时,mongodb不会替换空的timestamp.
db.test.insert({ts: new Timestamp(), _id: {ts: new Timestamp()}})
{"acknowledged" : true,"insertedId" : {"ts" : Timestamp(0, 0)}
}db.test.find()
{"_id" : {"ts" : Timestamp(0, 0) //_id字段中的时间戳未被替换},"ts" : Timestamp(1703731318, 1) //顶层字段的时间戳被替换成当前的操作时间
}
日期(Date)
日期类型是一个64位字符,表示了字1970年1月1日以来经过的毫秒数。日期时间是有符号的,负数表示1970年以前的时间。64位的字符,可以表示过去和现在共2.9亿年的时间。
var mydate1 = new Date()
var mydate2 = ISODate()
console.log(mydate1.toString())
console.log(mydate2.toString())
console.log(mydate1.getMonth())Thu Dec 28 2023 10:48:15 GMT+0800 (China Standard Time)
Thu Dec 28 2023 10:48:15 GMT+0800 (China Standard Time)
11
BSON类型的排序
在mongodb对BSON类型进行排序时,按照下面的类型进行排序。从小到大的顺序依次为
| 序号 | 类型 |
| 1 | MinKey |
| 2 | Null |
| 3 | Numbers(ints,longs,doubles,decimals) |
| 4 | String |
| 5 | Object |
| 6 | Array |
| 7 | BinData |
| 8 | ObjectId |
| 9 | Boolean |
| 10 | Date |
| 11 | Timestamp |
| 12 | RegularExpression |
| 13 | MaxKey |
这个排序怎样理解,不妨使用下面的测试用例来解释。插入13条各种类型的数据。当使用正序排列,即从小到大排列时,顺序从MinKey到MaxKey. 当使用倒序排列时,顺序相反。
db.test.insertMany([{value: MinKey()},{value: null},{value: 1},{value: "1"},{value: {a: 1}},{value: [1]},{value: new BinData(5,"1")},{value: ObjectId(1)},{value: true},{value: new Date()},{value: new Timestamp()},{value: /a/},{value: MaxKey()},])//正序排列
db.test.find().sort('value')
/* 1 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557ef"),"value" : MinKey()
},/* 2 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f0"),"value" : null
},/* 3 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f1"),"value" : 1
},/* 4 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f4"),"value" : [ 1 ]
},/* 5 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f2"),"value" : "1"
},/* 6 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f3"),"value" : {"a" : 1}
},/* 7 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f5"),"value" : MD5("")
},/* 8 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f6"),"value" : ObjectId("000000019ef5a82e298557ee")
},/* 9 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f7"),"value" : true
},/* 10 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f8"),"value" : ISODate("2023-12-28T11:04:43.958+08:00")
},/* 11 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f9"),"value" : Timestamp(1703732683, 1)
},/* 12 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557fa"),"value" : /a/
},/* 13 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557fb"),"value" : MaxKey()
}
//倒序排列
/* 1 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557fb"),"value" : MaxKey()
},/* 2 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557fa"),"value" : /a/
},/* 3 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f9"),"value" : Timestamp(1703732683, 1)
},/* 4 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f8"),"value" : ISODate("2023-12-28T11:04:43.958+08:00")
},/* 5 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f7"),"value" : true
},/* 6 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f6"),"value" : ObjectId("000000019ef5a82e298557ee")
},/* 7 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f5"),"value" : MD5("")
},/* 8 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f3"),"value" : {"a" : 1}
},/* 9 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f2"),"value" : "1"
},/* 10 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f1"),"value" : 1
},/* 11 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f4"),"value" : [ 1 ]
},/* 12 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557f0"),"value" : null
},/* 13 createdAt:12/28/2023, 11:04:43 AM*/
{"_id" : ObjectId("658ce5cb9ef5a82e298557ef"),"value" : MinKey()
}
数值类型的比较
mongodb比较数字类型时,int,long,double,decimal按照同一个类型进行比较。按照值大小进行排序。
字符串比较
默认字符串按照简单字节方法比较。即从第一个字符开始进行比较。当用户指定字符序时,mongodb比较字符串时,采用用户指定的字符序。
数组的比较
- 升序排列时,获取数组中最小的元素进行比较
- 降序排列时,比较数组中最大的元素
- 比较单元素数组与非数组数据时,mongodb会直接比较该数组中的元素和非数组元素值的大小。
- 空数组排列优先级别小于null或没有该字段的文档数据。
对象的比较
- 递归比较对象中的每一个键值对
- 字段类型相同时,比较字段名
- 字段名相同时,比较字段值
- 当前字段名,字段值都相同时,按照同样的方式比较下一个字段。字段较少的对象排列优先级小于字段多的对象。
日期和时间戳
日期排在时间错前
不存在字段
mongodb将不存在的字段看做空对象。即文档{ }与{a:null}的排列顺序相同
二进制数据
- 首先比较数据长度
- 数据长度相同时,比较子类型
- 数据长度和子类型相同时,按字节比较。
相关文章:
MongoDB 数据类型
目录 BSON 类型 二进制数据(Binary Data) ObjectId ObjectId定义 文档中的ObjectId ObjectId的单调性 字符串(String) 时间戳(Timestamps) 日期(Date) BSON类型的排序 数…...
Java 将 List 转换为 String常见方式
将 List 转换为 String的几种方式 使用 List的toString()方法将 List 转换为 String;结果前后会带有英文的中括号[],如:[1, 2, 3, 4, 5]使用Java8 stream流中的Collections.joining()方法,带有逗号分隔符或自定义分隔符将集合转成…...
Redis(认识NoSQL,认识redis,安装redis,redis桌面客户端,redis常见命令,redis的Java客户端)
文章目录 Redis快速入门1.初识Redis1.1.认识NoSQL1.1.1.结构化与非结构化1.1.2.关联和非关联1.1.3.查询方式1.1.4.事务1.1.5.总结 1.2.认识Redis1.3.安装Redis1.3.1.依赖库1.3.2.上传安装包并解压1.3.3.启动1.3.4.默认启动1.3.5.指定配置启动1.3.6.开机自启 1.4.Redis桌面客户端…...
idea 出现Cannot resolve symbol ‘springframework‘解决方法
Maven手动重新加载 1)File–>Invalidate Caches / Restart… 清理缓存,重启idea客户端 2)File–>Maven–>Reload project重新从maven中加载工程依赖的组件...
ubuntu22.04安装anacoda遇到的坑
这几天把用了3年的windows10换成了ubuntu22.04 各种环境都得配置,本文记录下遇到的坑。 1、anacoda在ubuntu上也可以用官方也提供了安装包,但是没有图形界面,需要以命令行的方式安装和运行配置 1.1 安装:官网下载后,…...
window的OPen方法,弹窗的特征
文章目录 一、介绍二、弹窗的特征 一、介绍 window.open() 方法是 JavaScript 中的一个内置方法,用于在浏览器中打开一个新的窗口或标签页。 语法: window.open(url, name, features, replace)二、弹窗的特征 open方法参数说明: 参数说明url要载入窗…...
DFS算法查找所有路径详解
DFS算法查找所有路径详解 算法介绍 深度优先搜索(Depth-First Search,DFS)是一种图遍历算法,它从起始节点开始,沿着一条路径尽可能深入,直到达到最深的节点,然后回溯到前一节点,继…...
单片机的存储、堆栈与程序执行方式
一、单片机存储区域 如图所示位STM32F103ZET6的参数: 单片机的ROM(内部FLASH):512KB,用来存放程序代码的空间。 单片机的RAM:64KB,一般都被分配为堆、栈、变量等的空间。 二、堆和栈的概念 …...
Web3开发成本和主要特性
多年来,技术不断进步,可帮助您的业务领先于竞争对手。如今,您可以看到许多更新和变化,使技术更加先进,对企业更加有用。到现在为止,web1.2和2.0比较流行,但是要知道web 3才是技术之父࿰…...
【数学建模美赛M奖速成系列】Matplotlib绘图技巧(一)
Matplotlib图像基础 写在前面1 基本绘图实例:sin、cos函数图2 plot()函数详解**kwargs参数: 3 matplotlib中绘图的默认配置4 设置图的横纵坐标的上下界5 设置横纵坐标上的记号6 调整图像的脊柱7 添加图例8 给一些特殊点加注释9 子图最后 写在前面 前面我…...
005、数据类型
1. 关于数据类型 Rust中,每个值都有其特定的数据类型,Rust会根据数据的类型来决定如何处理它们。 Rust是一门静态类型语言,它在编译程序的过程中就需要知道所有变量的具体类型。在大部分情况下,编译器可以根据我们如何绑定、使用变…...
软考网络工程师考试大纲(2018年最新版)
本书是全国计算机专业技术资格考试办公室组织编写的网络工程师考试大纲,本书除大纲内容外,还包括了人力资源和社会保障部、工业和信息化部的有关文件以及考试简介。 网络工程师考试大纲是针对本考试的计算机网络中级资格制定的。通过本考试的考生,可被用人单位择优聘任为工…...
【数据结构】栈【详解】
目录 栈的定义: 栈的声明与定义: 头文件的包含: 对栈的基本操作: 栈的初始化: 摧毁栈: 入栈: 编辑 出栈: 编辑 输出栈顶位置: 输出栈的当前大小: 判空操…...
CSS 纵向底部往上动画
<template><div class"container" mouseenter"startAnimation" mouseleave"stopAnimation"><!-- 旋方块 --><div class"box" :class"{ scale-up-ver-bottom: isAnimating }"><!-- 元素内容 --&g…...
常用的 MySQL 可视化客户端
数据库可视化客户端(GUI)让用户在和数据库进行交互时,能直观地查看、创建和修改对象,如:表、行和列。让数据库操作变得更方便了。 今天,我们来了解下目前市场上最常用的 MySQL 可视化客户端。 官方&#x…...
C#使用SyntaxTree获取.cs文件中的属性名和注释
有时候,我们可能需要获取.cs文件中的属性和对应的注释来生成一些代码,比如SQL查询什么的。 但使用正则匹配有时候会不准确。搜索了下,发现微软提供了代码解析的API。 具体如下两个方法: /// <summary> /// 获取所有属性和…...
基于价值认同的需求侧电能共享分布式交易策略(matlab完全复现)
目录 1 主要内容 2 部分程序 3 程序结果 4 下载链接 1 主要内容 该程序完全复现《基于价值认同的需求侧电能共享分布式交易策略》,针对电能共享市场的交易机制进行研究,提出了基于价值认同的需求侧电能共享分布式交易策略,旨在降低电力市…...
门控循环单元(GRU)-多输入回归预测
目录 一、程序及算法内容介绍: 基本内容: 亮点与优势: 二、实际运行效果: 三、部分程序: 四、全部代码数据分享: 一、程序及算法内容介绍: 基本内容: 本代码基于Matlab平台编译…...
电池管理系统BMS中SOC算法通俗解析(二)
下面简单介绍下我们BMS保护板使用的SOC估算方法。我们算法的主要是针对电流积分法计算SOC的局限性进行改进: ●电池包第一次上电使用开路电压法估算SOC。第一次上电,根据电池包厂家给出的电压和剩余容量二维关系图大概估算出目前电池包的剩余容量即SOC。…...
YOLOv5改进 | 2023主干篇 | 华为最新VanillaNet主干替换Backbone实现大幅度长点
一、本文介绍 本文给大家来的改进机制是华为最新VanillaNet网络,其是今年最新推出的主干网络,VanillaNet是一种注重极简主义和效率的神经网络架构。它的设计简单,层数较少,避免了像深度架构和自注意力这样的复杂操作(需要注意的是…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
稳定币的深度剖析与展望
一、引言 在当今数字化浪潮席卷全球的时代,加密货币作为一种新兴的金融现象,正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而,加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下,稳定…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
Python常用模块:time、os、shutil与flask初探
一、Flask初探 & PyCharm终端配置 目的: 快速搭建小型Web服务器以提供数据。 工具: 第三方Web框架 Flask (需 pip install flask 安装)。 安装 Flask: 建议: 使用 PyCharm 内置的 Terminal (模拟命令行) 进行安装,避免频繁切换。 PyCharm Terminal 配置建议: 打开 Py…...
pgsql:还原数据库后出现重复序列导致“more than one owned sequence found“报错问题的解决
问题: pgsql数据库通过备份数据库文件进行还原时,如果表中有自增序列,还原后可能会出现重复的序列,此时若向表中插入新行时会出现“more than one owned sequence found”的报错提示。 点击菜单“其它”-》“序列”,…...
ubuntu中安装conda的后遗症
缘由: 在编译rk3588的sdk时,遇到编译buildroot失败,提示如下: 提示缺失expect,但是实测相关工具是在的,如下显示: 然后查找借助各个ai工具,重新安装相关的工具,依然无解。 解决&am…...
深度解析云存储:概念、架构与应用实践
在数据爆炸式增长的时代,传统本地存储因容量限制、管理复杂等问题,已难以满足企业和个人的需求。云存储凭借灵活扩展、便捷访问等特性,成为数据存储领域的主流解决方案。从个人照片备份到企业核心数据管理,云存储正重塑数据存储与…...
