MongoDB文档和Bson类型

本文基于最新的v4.2版本进行介绍。

一、文档(Documents)

  1. 文档结构
  2. 点符号
  3. 文档的局限性
  4. 文档结构的其他用途

MongoDB将数据记录存储为BSON文档。BSON是JSON文档的二进制表示,它包含的数据类型比JSON多。


BSON主要会实现以下三点目标:
(1)更快的遍历速度
对JSON格式来说,太大的JSON结构会导致数据遍历非常慢。在JSON中,要跳过一个文档进行数据读取,需要对此文档进行扫描才行,需要进行麻烦的数据结构匹配,比如括号的匹配,而BSON对JSON的一大改进就是,它会将JSON的每一个元素的长度存在元素的头部,这样你只需要读取到元素长度就能直接seek到指定的点上进行读取了。
(2)操作更简易
对JSON来说,数据存储是无类型的,比如你要修改基本一个值,从9到10,由于从一个字符变成了两个,所以可能其后面的所有内容都需要往后移一位才可以。而使用BSON,你可以指定这个列为数字列,那么无论数字从9长到10还是100,我们都只是在存储数字的那一位上进行修改,不会导致数据总长变大。当然,在MongoDB中,如果数字从整形增大到长整型,还是会导致数据总长变大的。
(3)增加了额外的数据类型
JSON是一个很方便的数据交换格式,但是其类型比较有限。BSON在其基础上增加了“byte array”数据类型。这使得二进制的存储不再需要先base64转换后再存成JSON。大大减少了计算开销和数据大小。
但是,在有的时候,BSON相对JSON来说也并没有空间上的优势,比如对{“field”:7},在JSON的存储上7只使用了一个字节,而如果用BSON,那就是至少4个字节(32位)
目前在10gen的努力下,BSON已经有了针对多种语言的编码解码包。并且都是Apache 2 license下开源的。并且还在随着MongoDB进一步地发展。


1. 文档结构
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和death保存日期类型的值。
  • contribs包含一个字符串数组。
  • 视图持有NumberLong类型的值。

1.1 字段名称
字段名是字符串。
文档对字段名有以下限制:

  • 字段名_id保留为用作主键;它的值在集合中必须是唯一的,是不可变的,可以是数组以外的任何类型。
  • 字段名不能包含空字符。
  • 顶级字段名不能以美元符号($)开头。否则,从MongoDB 3.6开始,服务器允许存储包含点(即)和美元符号(即$)的字段名。

重要:
MongoDB查询语言不能总是有意义地表达对字段名包含这些字符的文档的查询(参见SERVER-30575)。
在查询语言中添加支持之前,使用$ and。不推荐使用字段名,官方的MongoDB驱动程序也不支持字段名。

BSON文档可能有多个具有相同名称的字段。然而,大多数MongoDB接口使用不支持重复字段名的结构(例如哈希表)表示MongoDB。如果需要操作具有多个同名字段的文档,请参阅driver documentation的驱动程序文档。

一些由内部MongoDB进程创建的文档可能有重复的字段,但是没有MongoDB进程会将重复的字段添加到现有的用户文档中。

1.2 字段值限制
通过MongoDB版本的特性兼容版本(fCV)设置为“4.0”或更早
对于索引的集合,索引字段的值具有最大索引键长度。有关详细信息,请参阅最大索引键长度。

2. 点符号
MongoDB使用点表示法来访问数组的元素和嵌入式文档的字段。
2.1 数组

若要通过从零开始的索引位置指定或访问数组中的元素,请将数组名称与点(.)和从零开始的索引位置连接起来,并用引号括起:

"<array>.<index>"

例如,给定文档中的以下字段:

{
   ...
   contribs: [ "Turing machine", "Turing test", "Turingery" ],
   ...
}

要指定contribs数组中的第三个元素,请使用点符号“contribs.2”。
有关查询数组的例子,请参阅:

  • 查询一个数组
  • 查询嵌入文档的数组

另请参阅:

  • $[]所有更新操作的位置运算符,
  • $[/<identifier/>]筛选更新操作的位置操作符,
  • $ position运算符用于更新操作,
  • 数组索引位置未知时的$投影操作符
  • 查询一个数组,以获得带有数组的点表示法示例。

2.2 嵌入的文件
要使用点符号指定或访问嵌入文档的字段,请将嵌入的文档名与点(.)和字段名连接起来,并在引号中括起:

"<embedded document>.<field>"

例如,给定文档中的以下字段:

{
   ...
   name: { first: "Alan", last: "Turing" },
   contact: { phone: { type: "cell", number: "111-222-3333" } },
   ...
}
  • 要在name字段中指定最后一个字段,请使用点符号“name.last”。
  • 要在联系人字段的电话文档中指定号码,请使用点符号“contact.phone.number”。

3. 文档的局限性
文件有以下属性:

3.1 文件大小限制
BSON文档的最大大小是16兆字节。
最大文档大小有助于确保单个文档不能使用过多的RAM,或者在传输期间不能使用过多的带宽。为了存储大于最大大小的文档,MongoDB提供了GridFS API。

3.2文档字段顺序
除了以下情况外,MongoDB在写操作中保留了文档字段的顺序:

  • _id字段总是文档中的第一个字段。
  • 包括重命名字段名的更新可能导致文档中字段的重新排序。

_id字段
在MongoDB中,存储在集合中的每个文档都需要一个惟一的_id字段作为主键。如果插入的文档省略了_id字段,MongoDB驱动程序将自动为_id字段生成ObjectId。
这也适用于通过upsert: true的更新操作插入的文档。

_id字段有以下行为和约束:

  • 默认情况下,MongoDB在创建集合期间在_id字段上创建惟一的索引。
  • _id字段总是文档中的第一个字段。如果服务器首先接收到一个没有_id字段的文档,那么服务器将把该字段移到开头。
  • _id字段可以包含除数组之外的任何BSON数据类型的值。

警告:
为了确保功能复制,不要在_id字段中存储BSON正则表达式类型的值。

以下是用于存储_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互操作性的信息,请参阅驱动程序文档。

注意:大多数MongoDB驱动程序客户端将包含_id字段,并在向MongoDB发送插入操作之前生成ObjectId;但是,如果客户机发送的文档没有_id字段,mongod将添加_id字段并生成ObjectId。

4. 文档结构的其他用途
除了定义数据记录之外,MongoDB还使用了整个文档结构,包括但不限于:查询过滤器、更新规范文档和索引规范文档
4.1 查询过滤器文件
查询筛选器文档指定了确定要为读取、更新和删除操作选择哪些记录的条件。
您可以使用<field>:<value>表达式来指定相等条件和查询操作符表达式。

{
  <field1>: <value1>,
  <field2>: { <operator>: <value> },
  ...
}

4.2 更新规范文档
Update规范文档使用Update操作符指定在db.collection.update()操作期间对特定字段执行的数据修改。

db.collection.update(
   <query>,
   <update>,
   {
     upsert: <boolean>,
     multi: <boolean>,
     writeConcern: <document>
   }
)
  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。
db.col.update({'title':'MongoDB 教程'},{$set:{'title':'MongoDB'}})

4.3 索引规范文档
索引规范文档定义要索引的字段和索引类型:

db.col.createIndex({"title":1,"description":-1})

创建索引,“title”升序,“description”降序。

二、BSON类型

本章介绍以下知识:

BSON是一种二进制序列化格式,用于在MongoDB中存储文档和进行远程过程调用。BSON规范位于bsonspec.org。
每个BSON类型都有整数和字符串标识符,如下表所示:

TypeNumberAliasNotes
Double1“double” 
String2“string” 
Object3“object” 
Array4“array” 
Binary data5“binData” 
Undefined6“undefined”Deprecated.
ObjectId7“objectId” 
Boolean8“bool” 
Date9“date” 
Null10“null” 
Regular Expression11“regex” 
DBPointer12“dbPointer”Deprecated.
JavaScript13“javascript” 
Symbol14“symbol”Deprecated.
JavaScript (with scope)15“javascriptWithScope” 
32-bit integer16“int” 
Timestamp17“timestamp” 
64-bit integer18“long” 
Decimal12819“decimal”New in version 3.4.
Min key-1“minKey” 
Max key127“maxKey” 

您可以使用这些值和$type操作符来查询文档的BSON类型。$type聚合运算符使用列出的BSON类型字符串之一返回运算符表达式的类型。
要确定字段的类型,请参阅Check Types in the mongo Shell
如果您将BSON转换为JSON,请参阅Extended JSON引用。
下面几节描述了对特定BSON类型的特殊考虑。

1. ObjectId
对象很小,可能是惟一的,生成速度快,并且是有序的。ObjectId值的长度为12字节,包括:

  • 一个4字节的时间戳值,表示ObjectId的创建,从Unix纪元开始以秒为单位度量。
  • 一个5字节的随机值
  • 一个3字节的递增计数器,初始化为一个随机值

虽然BSON格式本身是little-endian,但是时间戳和计数器值是big-endian,最重要的字节首先出现在字节序列中。
在MongoDB中,存储在集合中的每个文档都需要一个惟一的_id字段作为主键。如果插入的文档省略了_id字段,MongoDB驱动程序将自动为_id字段生成ObjectId。

MongoDB客户机应该使用唯一的ObjectId添加_id字段。将ObjectIds用于_id字段提供了以下额外好处:

  • 在mongo shell中,可以使用ObjectId. gettimestamp()方法访问ObjectId的创建时间。
  • 存储ObjectId值的_id字段上的排序大致相当于按创建时间排序

重要:
虽然ObjectId值应该随时间增加,但它们不一定是单调的。这是因为他们:

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

2. String

BSON字符串是UTF-8。通常,在序列化和反序列化BSON时,每种编程语言的驱动程序都会从该语言的字符串格式转换为UTF-8。这使得在BSON字符串中轻松存储大多数国际字符成为可能。此外,MongoDB $regex查询在regex字符串中支持UTF-8。

注意:给定使用UTF-8字符集的字符串,对字符串使用sort()将是合理正确的。但是,因为sort()在内部使用c++ strcmp api,所以排序顺序可能不正确地处理一些字符。

3. 时间戳
BSON有一个用于内部MongoDB的特殊时间戳类型,它与常规的日期类型没有关联。这个内部时间戳类型是一个64位的值,其中:

  • 最有效的32位是time_t值(自Unix纪元以来的秒)
  • 最不有效的32位是给定秒内操作的递增序数。

虽然BSON格式是little-endian格式,因此先存储最不重要的位,但是mongod实例总是在所有平台上比较time_t值之前的序号值,而不考虑endianness。
在单个mongod实例中,时间戳值总是惟一的。
在复制中,oplog有一个ts字段。该字段中的值反映操作时间,操作时间使用BSON时间戳值。

提示:BSON时间戳类型用于MongoDB内部使用。对于大多数情况,在应用程序开发中,您将希望使用BSON日期类型。

在插入包含空时间戳值的顶级字段的文档时,MongoDB使用当前时间戳值替换空时间戳值,并执行以下异常。如果_id字段本身包含一个空的时间戳值,它将始终按原样插入,而不是替换。

EXAMPLE

Insert a document with an empty timestamp value:

db.test.insertOne( { ts: new Timestamp() } );
Running db.test.find() would then return a document which resembles the following:

{ "_id" : ObjectId("542c2b97bac0595474108b48"), "ts" : Timestamp(1412180887, 1) }
服务器已经将ts的空时间戳值替换为插入时的时间戳值。

4. Date

BSON日期是一个64位整数,表示自Unix纪元(1970年1月1日)以来的毫秒数。这导致了大约2.9亿年的可代表的日期范围进入过去和未来。
正式的BSON规范将BSON日期类型称为UTC日期时间。
BSON日期类型已签名。[2]的负值表示1970年以前的日期。

EXAMPLE

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

var mydate1 = new Date()
EXAMPLE

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

var mydate2 = ISODate()
EXAMPLE

Return the Date value as string:

mydate1.toString()
EXAMPLE

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

mydate1.getMonth()

三、比较/排序顺序

介绍以下几点:

在比较不同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)

1. 数值类型
出于比较的目的,MongoDB将一些类型视为等效的。例如,数值类型在比较之前进行转换。

2. Strings

2.1 二进制比较
默认情况下,MongoDB使用简单的二进制比较来比较字符串。
2.2 排序
新版本3.4。
排序规则允许用户为字符串比较指定特定于语言的规则,例如针对lettercase和重音符号的规则。
排序规范有以下语法:

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

在指定排序规则时,locale字段是必需的;所有其他排序规则字段都是可选的。
如果没有为集合或操作指定排序规则,则MongoDB使用以前版本中用于字符串比较的简单二进制比较。

2.3 数组
对于数组,小于比较或升序排序比较数组的最小元素,大于比较或降序排序比较数组的最大元素。因此,当比较值为单元素数组(例如[1])的字段和值为非数组字段(例如2)时,比较的范围是1和2。空数组的比较(例如[])将空数组视为小于null或缺少字段。

2.4 对象
MongoDB对BSON对象的比较顺序如下:

  1. 按键值对在BSON对象中出现的顺序递归比较它们。
  2. 比较键字段名。
  3. 如果键字段名相等,则比较字段值。
  4. 如果字段值相等,比较下一个键/值对(返回到步骤1)。

2.5 日期和时间戳
日期对象在时间戳对象之前排序。
2.6 不存在的字段
该比较将不存在的字段视为空BSON对象。因此,文档{}和{a: null}中的a字段上的排序将按照排序顺序将文档视为等效的。

2.7 BinData
MongoDB按照以下顺序对BinData进行排序:

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

四、MongoDB Extended JSON (v2)

JSON只能直接表示BSON支持的类型的子集。为了保存类型信息,MongoDB将以下扩展添加到JSON格式中。

  • 规范的模式

        以牺牲可读性和互操作性为代价来强调类型保存的字符串格式。也就是说,从canonical到BSON的转换通常会保留类型信息,除非在某些特定的情况下。

  • Relaxed Mode

       一种强调可读性和互操作性的字符串格式,以牺牲类型保存为代价。也就是说,从轻松格式转换为BSON可能会丢失类型信息。

这两种格式都符合JSON RFC,可以被各种MongoDB驱动程序和工具解析。

MongoDB扩展了JSON v2的使用

Drivers(驱动)
以下驱动程序使用扩展的JSON v2.0

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

对于使用遗留MongoDB扩展JSON v1的c#和Ruby,请参考MongoDB扩展JSON (v1)。

MongoDB的命令行工具

Starting in version 4.2:

bsondump使用扩展JSON v2.0(规范模式)格式。
mongodump对元数据使用扩展JSON v2.0(规范模式)格式。需要mongorestore 4.2+版本,支持扩展JSON v2.0(规范模式或放宽)格式。
提示
通常,使用相应版本的mongodump和mongorestore。也就是说,要恢复用特定版本的mongodump创建的数据文件,使用相应版本的mongorestore。
mongoexport默认情况下以扩展JSON v2.0(放松模式)创建输出数据。
如果与——jsonFormat规范一起使用,则以扩展JSON v2.0(规范模式)创建输出数据。
mongoimport默认情况下,希望导入数据采用扩展JSON v2.0(放松模式或规范模式)。
如果指定了—legacy选项,则可以识别扩展JSON v1.0格式的数据。
提示
通常,mongoexport和mongoimport的版本应该匹配。也就是说,要导入从mongoexport创建的数据,您应该使用相应版本的mongoimport。

BSON数据类型和相关表示
下面介绍一些常见的BSON数据类型,以及规范化和非规范化的相关表示。

 

Array


CanonicalRelaxed
[ <elements> ]
<Same as Canonical>
Where the array elements are as follows:
  • <elements>

    数组元素使用扩展JSON。若要指定空数组,请省略内容 [ ].

Binary


CanonicalRelaxed
{ "$binary":
   {
      "base64": "<payload>",
      "subType": "<t>"
   }
}
<Same as Canonical>
Where the values are as follows:
  • "<payload>"

    Base64 encoded (with padding as “=”) payload string.

  • "<t>"

    对应于BSON二进制子类型的一个或两个字符的十六进制字符串。有关可用的子类型,请参阅扩展bson文档http://bsonspec.org/spec.html。

Date


For dates between years 1970 and 9999, inclusive:

CanonicalRelaxed
{"$date": {"$numberLong": "<millis>"}}
{"$date": "<ISO-8601 Date/Time Format>"}

For dates before year 1970 or after year 9999:

CanonicalRelaxed
{"$date": {"$numberLong": "<millis>"}}
<Same as Canonical>
Where the values are as follows:
  • "<millis>"

    作为字符串的64位带符号整数。该值表示相对于纪元的毫秒数。

  • "<ISO-8601 Date/Time Format>"

    一种ISO-8601互联网日期/时间格式的日期字符串。日期/时间的最大时间精度为毫秒:
    • 如果小数部分不为零,则小数秒正好有3位小数。
    • 否则,如果为0,则应省略小数秒。

Decimal128


New in version 3.4.

CanonicalRelaxed
{ "$numberDecimal": "<number>" }
<Same as Canonical>
Where the values are as follows:
  • "<number>"

    作为字符串的高精度小数。

Document


CanonicalRelaxed
{ <content> }
<Same as Canonical>
Where the document contents are as follows:
  • <content>

    Name:使用扩展JSON的值对。要指定空文档,请忽略内容 { }.

Double


For finite numbers:

CanonicalRelaxed
{"$numberDouble": "<decimal string>" }
<non-integer number>

For infinite numbers or NAN:

CanonicalRelaxed
{"$numberDouble": <"Infinity"|"-Infinity"|"NaN"> }
<Same as Canonical>
Where the values are as follows:
  • "<decimal string>"

    作为字符串的64位带符号浮点数。

  • <non-integer number>

    非整型数。整数被解析为整数而不是双精度数。

Int64


CanonicalRelaxed
{ "$numberLong": "<number>" }
<integer>
Where the values are as follows:
  • "<number>"

    A 64-bit signed integer as string.

  • <integer>

    A 64-bit signed integer.

Int32


CanonicalRelaxed
{ "$numberInt": "<number>" }
<integer>
Where the values are as follows:
  • "<number>"

    A 32-bit signed integer as string.

  • <integer>

    A 32-bit signed integer.

MaxKey


CanonicalRelaxed
{ "$maxKey": 1 }
<Same as Canonical>

MaxKey BSON数据类型比所有其他类型都要高。有关BSON类型的比较顺序的更多信息,请参见比较/排序顺序。

MinKey


CanonicalRelaxed
{ "$minKey": 1 }
<Same as Canonical>

MinKey BSON数据类型比所有其他类型都要低。有关BSON类型的比较顺序的更多信息,请参见比较/排序顺序。

ObjectId


CanonicalRelaxed
{ "$oid": "<ObjectId bytes>" }
<Same as Canonical>
Where the values are as follows:
  • "<ObjectId bytes>"

    一个由24个字符组成的十六进制字符串,表示ObjectId字节。

Regular Expression


CanonicalRelaxed
{ "$regularExpression":
   {
      "pattern": "<regexPattern>",
      "options": "<options>"
  }
}
<Same as Canonical>
Where the values are as follows:
  • "<regexPattern>"

    与正则表达式模式相对应的字符串。字符串可以包含有效的JSON字符和未转义的双引号(")字符,但不能包含未转义的正斜杠(/)字符。

  • "<options>"

    指定BSON正则表达式选项(' g '、' i '、' m '和' s ')或空字符串""的字符串。
    除了(' g ', ' i ', ' m '和' s ')选项将被删除时,转换到这个表示。
    重要的
    选项必须按字母顺序排列。

Timestamp


CanonicalRelaxed
{"$timestamp": {"t": <t>, "i": <i>}}
<Same as Canonical>
Where the values are as follows:
  • <t>

    自纪元以来的秒数为正整数。

  • <i>

    增量为正整数。

Example

Example Field Name

标准格式

简单格式
“_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}}

三、MongoDB Extended JSON (v1)

介绍以下几点:

  • MongoDB扩展了JSON v1和MongoDB驱动程序
  • 解析器和支持的格式
  • BSON数据类型和相关表示

JSON只能表示BSON支持的类型的子集。为了保存类型信息,MongoDB在JSON格式中添加了以下扩展:

  • 严格的模式。BSON类型的严格模式表示符合JSON RFC。任何JSON解析器都可以将这些严格的模式表示解析为键/值对;但是,只有MongoDB内部JSON解析器能够识别格式所传递的类型信息。
  • mongo Shell模式。MongoDB内部JSON解析器和mongo shell可以解析这种模式。

用于各种数据类型的表示取决于解析JSON的上下文。

1.MongoDB扩展了JSON v1和MongoDB驱动程序

以下驱动程序使用扩展的JSON v1.0(遗留)

  • c#
  • Ruby

对于其他驱动程序,请参考MongoDB扩展JSON (v2)。

2. 解析器和支持的格式

2.1 严格模式输入

下面的代码可以解析严格模式下的表示,并识别类型信息。

  • mongoimport 4.0及以上版本
  • --各种MongoDB工具的查询选项
  • MongoDB指南针

其他JSON解析器(包括mongo shell)可以将严格模式表示解析为键/值对,但不能识别类型信息。

2.2 mongo shell的输入模式

下面的代码可以解析mongo shell模式下的表示,并识别类型信息。

  • mongoimport 4.0及以上版本
  • --各种MongoDB工具的查询选项
  • mongo shell

2.3 严格模式输出

在版本4.2之前,MongoDB扩展JSON v1的严格模式下,MongoDB导出和REST及HTTP接口输出数据。

2.4 mongo shell的输出模式

在4.2版本之前,bsondump以mongo Shell模式输出。

3. BSON数据类型和相关表示

下面介绍了严格模式和mongo Shell模式下的BSON数据类型和相关表示。

Binary

data_binary

Strict Mode mongo Shell Mode
{ "$binary": "<bindata>", "$type": "<t>" }
 
BinData ( <t>, <bindata> )
  • <bindata>是二进制字符串的base64表示形式。
  • <t>是表示数据类型的单个字节。在严格模式下它是一个十六进制字符串,在外壳模式下它是一个整数。请参阅扩展的bson文档。http://bsonspec.org/spec.html

Date

data_date

Strict Mode mongo Shell Mode
{ "$date": "<date>" }
 
new Date ( <date> )

在严格模式下,<date>是ISO-8601日期格式,强制时区字段遵循模板YYYY-MM-DDTHH:mm:ss.mmm<+/-Offset>。
在Shell模式中,<date>是一个64位带符号整数的JSON表示,给出了从epoch UTC开始的毫秒数。

Timestamp

data_timestamp

Strict Mode mongo Shell Mode
{ "$timestamp": { "t": <t>, "i": <i> } }
 
Timestamp( <t>, <i> )
  • <t>是从epoch开始的32位无符号整数的JSON表示。
  • <i>是一个32位无符号整数。

Regular Expression

data_regex

Strict Mode mongo Shell Mode
{ "$regex": "<sRegex>", "$options": "<sOptions>" }
 
/<jRegex>/<jOptions>
  • <sRegex>是一个有效的JSON字符字符串。
  • <jRegex>是一个字符串,可能包含有效的JSON字符和未转义的双引号(")字符,但可能不包含未转义的正斜杠(/)字符。
  • <sOptions>是一个字符串,包含用字母表示的regex选项。
  • <jOptions>是一个字符串,可能只包含字符' g ', ' i ', ' m '和' s '(在v1.9中添加)。由于JavaScript和mongo Shell表示支持的选项范围有限,因此在转换为这种表示时,任何不符合约定的选项都将被删除。

OID

data_oid

Strict Mode mongo Shell Mode
{ "$oid": "<id>" }
 
ObjectId( "<id>" )

<id>是一个24个字符的十六进制字符串。

DB Reference

data_ref

Strict Mode mongo Shell Mode
{ "$ref": "<name>", "$id": "<id>" }
 
DBRef("<name>", "<id>")
  • <name>是一个有效的JSON字符字符串。
  • <id>是任何有效的扩展JSON类型。

Undefined Type

data_undefined

Strict Mode mongo Shell Mode
{ "$undefined": true }
 
undefined

JavaScript/BSON未定义类型的表示。
不能在查询文档中使用undefined。考虑一下插入到人员集合中的以下文档:

db.people.insert( { name : "Sally", age : undefined } )

以下查询返回一个错误:

db.people.find( { age : undefined } )
db.people.find( { age : { $gte : undefined } } )

但是,您可以使用$type查询未定义的值,如:

db.people.find( { age : { $type : 6 } } )

此查询返回年龄字段值未定义的所有文档。

MinKey

data_minkey

Strict Mode mongo Shell Mode
{ "$minKey": 1 }
 
MinKey

MinKey BSON数据类型的表示,它比所有其他类型都低。有关BSON类型的比较顺序的更多信息,请参见比较/排序顺序。

MaxKey

data_maxkey

Strict Mode mongo Shell Mode
{ "$maxKey": 1 }
 
MaxKey

MaxKey BSON数据类型的表示,它比所有其他类型都要高。有关BSON类型的比较顺序的更多信息,请参见比较/排序顺序。

NumberLong

data_numberlong

Strict Mode mongo Shell Mode
{ "$numberLong": "<number>" }
 
NumberLong( "<number>" )

NumberLong是一个64位有符号整数。您必须包含引号,否则它将被解释为浮点数,从而导致准确性的损失。
例如,下面的命令将9223372036854775807作为一个有和没有引号围绕整数值的数字插入:

db.json.insert( { longQuoted : NumberLong("9223372036854775807") } )
db.json.insert( { longUnQuoted : NumberLong(9223372036854775807) } )

当您检索文档时,longunquote的值发生了变化,而longquote仍然保持其准确性:

db.json.find()
{ "_id" : ObjectId("54ee1f2d33335326d70987df"), "longQuoted" : NumberLong("9223372036854775807") }
{ "_id" : ObjectId("54ee1f7433335326d70987e0"), "longUnQuoted" : NumberLong("-9223372036854775808") }

NumberDecimal

New in version 3.4.

data_numberdecimal

Strict Mode mongo Shell Mode
{ "$numberDecimal": "<number>" }
 
NumberDecimal( "<number>" )

NumberDecimal是一个高精度的小数。必须包含引号,否则输入数字将被视为双引号,从而导致数据丢失。
例如,以下命令将123.40作为带引号和不带引号的数字小数插入值:

db.json.insert( { decimalQuoted : NumberDecimal("123.40") } )
db.json.insert( { decimalUnQuoted : NumberDecimal(123.40) } )

当您检索文档时,decimalunquote的值发生了变化,而decimalquote保留了指定的精度:

db.json.find()
{ "_id" : ObjectId("596f88b7b613bb04f80a1ea9"), "decimalQuoted" : NumberDecimal("123.40") }
{ "_id" : ObjectId("596f88c9b613bb04f80a1eaa"), "decimalUnQuoted" : NumberDecimal("123.400000000000") }

 

  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值