[mongo] 1.4 mongodb BSON 和 JSON 数据类型

举报
dber 发表于 2021/01/25 21:34:01 2021/01/25
【摘要】 BSON是一种二进制格式,用于在MongoDB中存储文档和进行远程过程调用。BSON规范位于bsonspec.org。每种BSON类型都具有整数和字符串标识符,如下表所示:Type Number Alias NotesDouble 1 “double”  String 2 “string”  Object 3 “object”  Array 4 “array”  Binary data 5 ...

BSON是一种二进制格式,用于在MongoDB中存储文档和进行远程过程调用。BSON规范位于bsonspec.org

每种BSON类型都具有整数和字符串标识符,如下表所示:

Type Number Alias Notes
Double 1 “double”  
String 2 “string”  
Object 3 “object”  
Array 4 “array”  
Binary data 5 “binData”  
Undefined 6 “undefined” Deprecated.
ObjectId 7 “objectId”  
Boolean 8 “bool”  
Date 9 “date”  
Null 10 “null”  
Regular Expression 11 “regex”  
DBPointer 12 “dbPointer” Deprecated.
JavaScript 13 “javascript”  
Symbol 14 “symbol” Deprecated.
JavaScript code with scope 15 “javascriptWithScope” Deprecated in MongoDB 4.4.
32-bit integer 16 “int”  
Timestamp 17 “timestamp”  
64-bit integer 18 “long”  
Decimal128 19 “decimal” New in version 3.4.
Min key -1 “minKey”  
Max key 127 “maxKey”  

  • $type操作支持查询BSON类型。$type还支持数字别名,该别名与 integer, decimal, double, and long 类型匹配。
  • $type集合运算符返回其参数的BSON类型。
  • 如果参数是BSON integer, decimal, double, and long 类型,$isNumber聚合运算符返回true4.4版新功能

要确定字段的类型,请参阅Check Types in the mongo Shell.

如果将BSON转换为JSON,请参阅扩展JSON参考。

以下各节描述了特定BSON类型的特殊注意事项。

ObjectId

ObjectId很小,很可能是唯一的,可以快速生成并排序。ObjectId值的长度为12字节,由以下组成:

  • 一个4字节的时间戳记值,代表自Unix时代以来以秒为单位的ObjectId的创建
  • 5字节随机值
  • 3字节递增计数器,初始化为随机值

虽然BSON格式本身是小字节序,但时间戳和 计数器值却是大字节序,最重要字节出现在字节序列首位。

在MongoDB中,存储在集合中的每个文档都有一个唯一的 _id字段作为主键。如果插入的文档省略了该_id字段,则MongoDB驱动程序会自动为_id字段生成一个ObjectId

也可通过upsert:true 更新操作插入文档。

MongoDB客户端应添加一个_id,其具有唯一ObjectId的值。_id字段中使用ObjectIds具有以下额外优点:

  • mongoshell中,您可以通过ObjectId使用ObjectId.getTimestamp()方法访问的创建时间。

  • _id存储ObjectId值的字段上进行排序大致相当于按创建时间进行排序。

    重要

    尽管ObjectId值应随时间增加,但不一定是单调的:

    • 仅包含一秒的时间分辨率,因此 在同一秒内创建的ObjectId值没有保证的顺序。
    • 由客户端生成,可能具有不同的系统时钟。

扩展

ObjectId()

字符串

BSON字符串为UTF-8。通常,在对BSON进行序列化和反序列化时,每种编程语言的驱动程序都会从​​该语言的字符串格式转换为UTF-8。这样就可以轻松地将大多数国际字符存储在BSON字符串中。 [1]此外,MongoDB $regex查询在正则表达式字符串中支持UTF-8。

[1] 给定使用UTF-8字符集的sort()字符串,在字符串上使用将是正确的。但是,由于内部 sort()使用C ++ strcmpAPI,因此排序顺序可能会错误地处理某些字符。

时间戳

BSON有一个特殊的时间戳类型MongoDB内部使用, 与常规相关的日期 类型没有关联。内部时间戳记类型是64位,其中:

  • 最高的32位是一个time_t值(自Unix时代以来的秒数)
  • 最低的32位是ordinal给定秒内操作的增量。

尽管BSON格式是小字节序的,首先存储了最低位,但是无论字节序如何,mongod实例始终在所有平台上先比较time_t序数

mongod实例中,时间戳记值始终是唯一的。

在复制中,操作日志具有一个ts字段。该字段中的值反映了使用BSON时间戳值的操作时间。

注意

BSON时间戳类型供 MongoDB 内部使用。在大多数情况下,在程序开发中,需要使用BSON日期类型。有关更多信息,请参见日期

当插入包含带有空时间戳值的顶级字段的文档时,MongoDB会将空时间戳值替换为当前时间戳值,但如果_id 字段本身包含空的时间戳记值,则将始终按原样插入而不替换它。

插入带有空时间戳值的文档:


db.test.insertOne( { ts: new Timestamp() } ); 

db.test.find() 然后,运行将返回类似于以下内容的文档:

{ "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1) }

服务使用插入时的时间戳值替换了ts字段空的时间戳值。

日期

BSON Date是一个64位整数,代表自Unix纪元(1970年1月1日)以来的毫秒数。这导致可以追溯到过去和未来约2.9亿年的日期范围。

官方BSON规格 指的是BSON Date类型为UTC日期时间

BSON日期类型已标记的。[2]负值表示1970年之前的日期。


EXAMPLE

Construct a Date using the new Date() constructor in the mongo shell:

var mydate1 = new Date()

Construct a Date using the ISODate() constructor in the mongo shell:

var mydate2 = ISODate()

Return the Date value as string:

mydate1.toString()
Return the month portion of the Date value; months are zero-indexed, so that January is month 0:

mydate1.getMonth()

[2] Prior to version 2.0, Date values were incorrectly interpreted as unsigned integers, which affected sorts, range queries, and indexes on Date fields. Because indexes are not recreated when upgrading, please re-index if you created an index on Date values with an earlier version, and dates before 1970 are relevant to your application.



比较和排序

比较不同BSON类型的值时,MongoDB使用以下比较顺序,从最低到最高:

  1. MinKey (internal type)
  2. Null
  3. Numbers (ints, longs, doubles, decimals)
  4. Symbol, String
  5. Object
  6. Array
  7. BinData
  8. ObjectId
  9. Boolean
  10. Date
  11. Timestamp
  12. Regular Expression
  13. MaxKey (internal type)

数值类型

为了进行比较,MongoDB将某些类型视为等效。例如,数字类型在比较之前先进行转换。

字符串

二进制比较

默认情况下,MongoDB使用简单的二进制比较来比较字符串。

排序

3.4版的新功能。

排序允许用户为字符串比较指定特定于语言的规则,例如字母大写和重音符号的规则。

排序规范具有以下语法:


{
   locale: <string>,
   caseLevel: <boolean>,
   caseFirst: <string>,
   strength: <int>,
   numericOrdering: <boolean>,
   alternate: <string>,
   maxVariable: <string>,
   backwards: <boolean>
}



指定排序规则时,locale为必填字段;所有其他排序规则字段都是可选的。有关字段的说明,请参见 Collation Document

如果没有为集合或操作指定排序规则,则MongoDB使用先前版本中使用的简单二进制进行字符串比较。

数组

对于数组,“小于”操作或升序排序比较数组的最小元素,“大于”操作或降序排序比较数组的最大元素。这样,当值是单元素数组(例如 [ 1 ])的字段与非数组字段(例如 2 )进行比较时,是1和2之间的比较 。空数组(例如 [ ])的比较将空数组视为小于 null 或缺少字段。

对象

MongoDB对BSON对象的比较使用以下顺序:

  1. 以键值对在BSON对象中出现的顺序递归比较它们。
  2. 比较字段类型。MongoDB对字段类型使用以下比较顺序,从最低到最高:
    1. MinKey (internal type)
    2. Null
    3. Numbers (ints, longs, doubles, decimals)
    4. Symbol, String
    5. Object
    6. Array
    7. BinData
    8. ObjectId
    9. Boolean
    10. Date
    11. Timestamp
    12. Regular Expression
    13. MaxKey (internal type)
  3. 如果字段类型相等,则比较 关键字段名称
  4. 如果关键字段名称相等,则比较字段值。
  5. 如果字段值相等,则比较下一个键/值对(返回步骤1)。直到没有其他对的对象小于具有其他对的对象。

日期和时间戳

日期对象在时间戳对象之前排序。

不存在的字段

比较将不存在的字段视为空BSON对象。因此,在{ } and { a: null } 的文档排序处理等同于顺序排序。

BinData 

MongoDB按以下顺序排序BinData类型

  1. 首先,数据的长度或大小。
  2. 然后,BSON的一字节子类型。
  3. 最后,根据数据执行逐字节比较。


MongoDB Extended JSON (v1)

可参考官方文档。


MongoDB Extended JSON (v2)

JSON可以看做是BSON的子集。为了保留类型信息,MongoDB将以下扩展添加到JSON格式。

  • 标准模式(Canonical
    一种字符串格式,该格式强调类型保留,但会牺牲可读性和互操作性。也就是说,除特定情况下,从标准到BSON的转换通常会保留类型信息。
  • 宽松模式(Relaxed
    一种字符串格式,它以保留类型为代价来强调可读性和互操作性。也就是说,从宽松格式转换为BSON可能会丢失类型信息。

两种格式都符合JSON RFC,并且可以通过各种MongoDB驱动程序和工具进行解析。


MongoDB扩展JSON v2用法

Drivers

The following drivers use the Extended JSON v2.0

  • C
  • C++
  • Go
  • Java
  • Node
  • Perl
  • PHPC
  • Python
  • Scala

For C# and Ruby that use Legacy MongoDB Extended JSON v1, refer to MongoDB Extended JSON (v1).

MongoDB命令行工具

从4.2版开始:

bsondump 使用扩展JSON v2.0(规范模式)格式。
mongodump

对元数据使用扩展的JSON v2.0(规范模式)格式。需要mongorestore4.2+版本,该版本支持扩展JSON v2.0(标准模式或宽松模式)格式。

建议

在一般情况下,使用相应的版本 mongodumpmongorestore。也就是说,要还原使用特定版本创建的数据文件mongodump,请使用的相应版本mongorestore

mongoexport
默认情况下,以扩展JSON v2.0(轻松模式)创建输出数据。
如果与一起使用,则以扩展JSON v2.0(规范模式)创建输出数据--jsonFormat
mongoimport
预期导入数据默认为扩展JSON v2.0(轻松模式或规范模式)。
如果--legacy指定了选项,则可以识别扩展JSON v1.0格式的 数据。

建议

在一般情况下,的版本mongoexport和 mongoimport应该匹配。也就是说,要导入从创建的数据mongoexport,您应该使用的相应版本mongoimport

BSON数据类型和关联的表示形式

下面介绍了一些常见的BSON数据类型以及CanonicalRelaxed中的相关表示形式。

有关完整列表,请参见 https://github.com/mongodb/specifications/blob/master/source/extended-json.rst#conversion-table

Array

标准 宽松

[<elements>]

<与标准模式相同>
其中数组元素如下:
  • <elements>
    数组元素使用扩展JSON。要指定一个空数组,请省略content [ ]。
Binary

标准 宽松

{ "$binary": 
{
"base64": "<payload>",
"subType": "<t>"
}
}

<与规标准相同>
值如下:
  • "<payload>"
    Base64编码(填充为“ =”)有效负载字符串。
  • "<t>"
    一个或两个字符的十六进制字符串,对应于BSON二进制子类型。有关可用的子类型,请参阅扩展的bson文档 http://bsonspec.org/spec.html
Date

For dates before year 1970 or after year 9999:
Canonical Relaxed

{"$date": {"$numberLong": "<millis>"}}

<Same as Canonical>
Where the values are as follows:
  • "<millis>"
    • 一个64位带符号整数作为字符串。该值表示相对于纪元的毫秒数。
  • "<ISO-8601 Date/Time Format>"
    A date in ISO-8601 Internet Date/Time Format as string. 日期/时间的最大时间精度为毫秒:
    • 如果小数部分不为零,则小数秒将精确到小数点后三位。
    • 否则,如果为零,则应忽略小数秒

Decimal128

New in version 3.4.

Canonical Relaxed

{ "$numberDecimal": "<number>" }

<Same as Canonical>
Where the values are as follows:
Document

Canonical Relaxed

{ <content> }

<Same as Canonical>
Where the document contents are as follows:
  • <content>
    Name:value pairs that use Extended JSON. To specify an empty document, omit the content { }.
Double

For finite numbers:

Canonical Relaxed

{"$numberDouble": "<decimal string>" }

<non-integer number>

For infinite numbers or NAN:

Canonical Relaxed

{"$numberDouble": <"Infinity"|"-Infinity"|"NaN"> }

<Same as Canonical>
Where the values are as follows:
  • "<decimal string>"
    A 64-bit signed floating point as a string.
  • <non-integer number>
    A non-integer number. Integer numbers are parsed as integer instead of double.
Int64

Canonical Relaxed

{ "$numberLong": "<number>" }

<integer>
Where the values are as follows:
  • "<number>"
    A 64-bit signed integer as string.
  • <integer>
    A 64-bit signed integer.
Int32

Canonical Relaxed

{ "$numberInt": "<number>" }

<integer>
Where the values are as follows:
  • "<number>"
    A 32-bit signed integer as string.
  • <integer>
    A 32-bit signed integer.
MaxKey

Canonical Relaxed

{ "$maxKey": 1 }

<Same as Canonical>

The MaxKey BSON data type compares higher than all other types. See Comparison/Sort Order for more information on comparison order for BSON types.

MinKey

Canonical Relaxed

{ "$minKey": 1 }

<Same as Canonical>

The MinKey BSON data type compares lower than all other types. See Comparison/Sort Order for more information on comparison order for BSON types.

ObjectId

Canonical Relaxed

{ "$oid": "<ObjectId bytes>" }

<Same as Canonical>
Where the values are as follows:
  • "<ObjectId bytes>"
    A 24-character, big-endian hexadecimal string that represents the ObjectId bytes.
Regular Expression

Canonical Relaxed

{ "$regularExpression":
   {
      "pattern": "<regexPattern>",
      "options": "<options>"
  }
}

<Same as Canonical>
Where the values are as follows:
  • "<regexPattern>"

    A string that corresponds to the regular expression pattern. The string can contain valid JSON characters and unescaped double quote (") characters, but may not contain unescaped forward slash (/) characters.

  • "<options>"

    A string that specifies BSON regular expression options (‘g’, ‘i’, ‘m’ and ‘s’) or an empty string "".

    Options other than (‘g’, ‘i’, ‘m’ and ‘s’) will be dropped when converting to this representation.

    IMPORTANT

    The options MUST be in alphabetical order.

Timestamp

Canonical Relaxed

{"$timestamp": {"t": <t>, "i": <i>}}

<Same as Canonical>
Where the values are as follows:
  • <t>
    A positive integer for the seconds since epoch.
  • <i>
    A positive integer for the increment.

Example

Example Field Name Canonical Format Relaxed Format
“_id:” {“$oid”:”5d505646cf6d4fe581014ab2”} {“$oid”:”5d505646cf6d4fe581014ab2”}
“arrayField”: [“hello”,{“$numberInt”:”10”}] [“hello”,10]
“dateField”: {“$date”:{“$numberLong”:”1565546054692”}} {“$date”:”2019-08-11T17:54:14.692Z”}
“dateBefore1970”: {“$date”:{“$numberLong”:”-1577923200000”}} {“$date”:{“$numberLong”:”-1577923200000”}}
“decimal128Field”: {“$numberDecimal”:”10.99”} {“$numberDecimal”:”10.99”}
“documentField”: {“a”:”hello”} {“a”:”hello”}
“doubleField”: {“$numberDouble”:”10.5”} 10.5
“infiniteNumber” {“$numberDouble”:”Infinity”} {“$numberDouble”:”Infinity”}
“int32field”: {“$numberInt”:”10”} 10
“int64Field”: {“$numberLong”:”50”} 50
“minKeyField”: {“$minKey”:1} {“$minKey”:1}
“maxKeyField”: {“$maxKey”:1} {“$maxKey”:1}
“regexField”: {“$regularExpression”:{“pattern”:”^H”,”options”:”i”}} {“$regularExpression”:{“pattern”:”^H”,”options”:”i”}}
“timestampField”: {“$timestamp”:{“t”:1565545664,”i”:1}} {“$timestamp”:{“t”:1565545664,”i”:1}}







【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。