文档菜单
文档首页
/ / /
Ruby MongoDB 驱动程序
/

BSON 教程

本页内容

  • 安装
  • 与 ActiveSupport 一起使用
  • BSON 序列化
  • 字节数组
  • 写入
  • 读取
  • 支持类
  • BSON::Binary
  • BSON::Code
  • BSON::CodeWithScope
  • BSON::DBRef
  • BSON::Document
  • BSON::MaxKey
  • BSON::MinKey
  • BSON::ObjectId
  • BSON::Timestamp
  • BSON::Undefined
  • BSON::Decimal128
  • 符号
  • JSON 序列化
  • 时间实例
  • DateTime 实例
  • Date 实例
  • 正则表达式
  • Ruby 与 MongoDB 正则表达式
  • BSON::Regexp::Raw
  • 正则表达式转换
  • 读取和写入
  • 键顺序
  • 重复键

本教程讨论了使用 Ruby BSON 库。

BSON库可以从以下位置安装:Ruby gems手动安装或使用bundler。

手动安装gem:

gem install bson

要使用bundler安装gem,请将以下内容添加到您的gemfile:

gem 'bson'

BSON库与MRI >= 2.5和JRuby >= 9.2兼容。

ActiveSupport定义的类,如TimeWithZone,默认不进行序列化,以避免BSON对ActiveSupport的硬依赖。当在也使用ActiveSupport的应用程序中使用BSON时,必须显式地引入ActiveSupport相关的代码

require 'bson'
require 'bson/active_support'

获取 Ruby 对象的原始 BSON 表示形式,通过在 Ruby 对象上调用 to_bson 实现,这将返回一个 BSON::ByteBuffer。例如

"Shall I compare thee to a summer's day".to_bson
1024.to_bson

从 BSON 生成对象,通过在您想要实例化的类上调用 from_bson 并传递一个 BSON::ByteBuffer 实例来完成。

String.from_bson(byte_buffer)
BSON::Int32.from_bson(byte_buffer)

BSON 库 4.0 引入了在 MRI 和 JRuby 中使用原生字节缓冲区,而不是使用 StringIO,以提高性能。

要创建用于写入(即序列化为 BSON)的 ByteBuffer,无需传递任何参数实例化 BSON::ByteBuffer

buffer = BSON::ByteBuffer.new

要将原始字节写入字节缓冲区而不进行转换,请使用 put_byteput_bytes 方法。它们接受一个字节字符串作为参数,并将此字符串复制到缓冲区中。put_byte 强制要求参数是长度为 1 的字符串;put_bytes 接受任何长度的字符串。字符串可以包含空字节。

buffer.put_byte("\x00")
buffer.put_bytes("\xff\xfe\x00\xfd")

注意

put_byteput_bytes 在将参数写入字节缓冲区之前不会写入 BSON 类型字节。

后续的写入方法将特定类型的对象写入 BSON 规范。请注意,由方法名称指示的类型优先于参数的类型 - 例如,如果将浮点值传递给 put_int32,则将其强制转换为整数,并将得到的整数写入字节缓冲区。

要将 UTF-8 字符串(BSON 类型 0x02)写入字节缓冲区,请使用 put_string

buffer.put_string("hello, world")

请注意,BSON 字符串始终以 UTF-8 编码。因此,参数必须是 UTF-8 或可转换为 UTF-8 的编码(即非二进制)。如果参数不是 UTF-8 编码,则先将字符串转换为 UTF-8,然后将 UTF-8 编码的版本写入缓冲区。字符串必须在所声明的编码中有效,包括如果编码是 UTF-8,则必须为有效的 UTF-8。字符串可以包含空字节。

BSON 规范还定义了一个 CString 类型,例如用于文档键。要将 CString 写入缓冲区,请使用 put_cstring

buffer.put_cstring("hello, world")

与常规字符串一样,BSON 中的 CString 必须是 UTF-8 编码。如果参数不是 UTF-8,则将其转换为 UTF-8,然后将得到的字符串写入缓冲区。与 put_string 不同,传递给 put_cstring 的参数的 UTF-8 编码不能包含任何空字节,因为 BSON 中的 CString 序列化格式是空终止的。

put_string 不同,put_cstring 还接受符号和整数。在所有情况下,在写入之前都会将参数转换为字符串。

buffer.put_cstring(:hello)
buffer.put_cstring(42)

要将 32 位或 64 位整数写入字节缓冲区,请分别使用 put_int32put_int64 方法。请注意,Ruby 整数可以是任意大的;如果要写入的值超出了 32 位或 64 位整数的范围,put_int32put_int64 会引发 RangeError

buffer.put_int32(12345)
buffer.put_int64(123456789012345)

注意

如果 put_int32put_int64 接收到浮点数参数,则首先将参数强制转换为整数,然后将整数写入字节缓冲区。

要将64位浮点值写入字节数据缓冲区,请使用put_double

buffer.put_double(3.14159)

要获取序列化数据作为字节字符串(例如,通过套接字发送数据),请对缓冲区调用to_s

buffer = BSON::ByteBuffer.new
buffer.put_string('testing')
socket.write(buffer.to_s)

注意

ByteBuffer分别跟踪读取和写入位置。无法重置缓冲区以进行写入 - rewind仅影响读取位置。

要创建用于读取的ByteBuffer(即从BSON反序列化),请使用字节字符串作为参数实例化BSON::ByteBuffer

buffer = BSON::ByteBuffer.new(string) # a read mode buffer.

读取缓冲区是通过以下API完成的

buffer.get_byte # Pulls a single byte from the buffer.
buffer.get_bytes(value) # Pulls n number of bytes from the buffer.
buffer.get_cstring # Pulls a null-terminated string from the buffer.
buffer.get_double # Pulls a 64-bit floating point from the buffer.
buffer.get_int32 # Pulls a 32-bit integer (4 bytes) from the buffer.
buffer.get_int64 # Pulls a 64-bit integer (8 bytes) from the buffer.
buffer.get_string # Pulls a UTF-8 string from the buffer.

要重新从缓冲区的开始位置读取,请使用rewind

buffer.rewind

注意

ByteBuffer分别跟踪读取和写入位置。rewind仅影响读取位置。

具有BSON规范中表示的表示并为其定义了to_bson方法的Ruby核心类包括:ObjectArrayFalseClassFloatHashIntegerBigDecimalNilClassRegexpStringSymbol(已弃用),TimeTrueClass

除了核心Ruby对象外,BSON还提供了一些特定于规范的专用类型

使用 BSON::Binary 对象来存储任意二进制数据。可以从以下二进制字符串构造 Binary 对象

BSON::Binary.new("binary_string")
# => <BSON::Binary:0x47113101192900 type=generic data=0x62696e6172795f73...>

默认情况下,Binary 对象以 BSON 二进制子类型 0 (:generic) 创建。可以显式指定子类型,以表示字节编码的数据类型

BSON::Binary.new("binary_string", :user)
# => <BSON::Binary:0x47113101225420 type=user data=0x62696e6172795f73...>

有效的子类型有 :generic:function:old:uuid_old:uuid:md5:user

可以使用 datatype 属性从 Binary 实例中检索数据和子类型,如下所示

binary = BSON::Binary.new("binary_string", :user)
binary.data
=> "binary_string"
binary.type
=> :user

注意

BSON::Binary 对象始终以 BINARY 编码存储数据,而不管构造函数中传入的字符串的编码方式如何

str = "binary_string"
str.encoding
# => #<Encoding:US-ASCII>
binary = BSON::Binary.new(str)
binary.data
# => "binary_string"
binary.data.encoding
# => #<Encoding:ASCII-8BIT>

要从其 RFC 4122 兼容的字符串表示形式创建 UUID BSON::Binary (二进制子类型 4),请使用 from_uuid 方法

uuid_str = "00112233-4455-6677-8899-aabbccddeeff"
BSON::Binary.from_uuid(uuid_str)
# => <BSON::Binary:0x46986653612880 type=uuid data=0x0011223344556677...>

要将 UUID BSON::Binary 转换为 RFC 4122 兼容的表示形式,请使用 to_uuid 方法

binary = BSON::Binary.new("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF".force_encoding('BINARY'), :uuid)
=> <BSON::Binary:0x46942046606480 type=uuid data=0x0011223344556677...>
binary.to_uuid
=> "00112233-4455-6677-8899aabbccddeeff"

在调用 from_uuidto_uuid 方法时,可以显式指定标准表示

binary = BSON::Binary.from_uuid(uuid_str, :standard)
binary.to_uuid(:standard)

请注意,:standard 表示只能与子类型为 :uuid 的 Binary 一起使用(不能与 :uuid_old 一起使用)。

存储在BSON::Binary对象(子类型3::uuid_old)中的数据可能以三种不同的字节顺序持久化,具体取决于创建数据的驱动程序。字节顺序包括CSharp旧版、Java旧版和Python旧版。Python旧版字节顺序与标准RFC 4122字节顺序相同;CSharp旧版和Java旧版字节顺序中的某些字节已交换。

包含旧版UUID的Binary对象不编码UUID存储的格式。因此,将旧版UUID格式转换为和从其转换的方法以所需的格式或表示作为它们的参数。应用程序可以复制旧版UUID Binary对象,而无需知道它们存储数据时的字节顺序。

以下提供了一些处理旧版UUID的方法,以与存储在旧版UUID格式中的现有部署进行互操作。建议新应用程序仅使用:uuid(子类型4)格式,该格式符合RFC 4122。

要将旧版UUID BSON::Binary转换为字符串,请使用指定所需表示的to_uuid方法。接受的表示包括:csharp_legacy:java_legacy:python_legacy。请注意,如果不指定表示,则无法将旧版UUID BSON::Binary转换为字符串。

binary = BSON::Binary.new("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF".force_encoding('BINARY'), :uuid_old)
=> <BSON::Binary:0x46942046606480 type=uuid data=0x0011223344556677...>
binary.to_uuid
# => ArgumentError (Representation must be specified for BSON::Binary objects of type :uuid_old)
binary.to_uuid(:csharp_legacy)
# => "33221100-5544-7766-8899aabbccddeeff"
binary.to_uuid(:java_legacy)
# => "77665544-3322-1100-ffeeddccbbaa9988"
binary.to_uuid(:python_legacy)
# => "00112233-4455-6677-8899aabbccddeeff"

要从UUID的字符串表示形式创建旧版UUID BSON::Binary,请使用指定所需表示的from_uuid方法

uuid_str = "00112233-4455-6677-8899-aabbccddeeff"
BSON::Binary.from_uuid(uuid_str, :csharp_legacy)
# => <BSON::Binary:0x46986653650480 type=uuid_old data=0x3322110055447766...>
BSON::Binary.from_uuid(uuid_str, :java_legacy)
# => <BSON::Binary:0x46986653663960 type=uuid_old data=0x7766554433221100...>
BSON::Binary.from_uuid(uuid_str, :python_legacy)
# => <BSON::Binary:0x46986653686300 type=uuid_old data=0x0011223344556677...>

这些方法可用于将一种表示转换为另一种表示

BSON::Binary.from_uuid('77665544-3322-1100-ffeeddccbbaa9988',:java_legacy).to_uuid(:csharp_legacy)
# => "33221100-5544-7766-8899aabbccddeeff"

表示JavaScript代码字符串。

BSON::Code.new("this.value = 5;")

注意

自 MongoDB 4.2.1 版本开始,CodeWithScope 类型已被弃用。从 MongoDB 4.4 版本开始,CodeWithScope 将不再支持各种服务器命令和运算符,如 $where。在使用 MongoDB 4.4 及更高版本时,请使用其他 BSON 类型和其他运算符。

表示包含值哈希的 JavaScript 代码字符串。

BSON::CodeWithScope.new("this.value = age;", age: 5)

这是 BSON::Document 的子类,提供了对 DBRef 的集合、id 和数据库的访问器。

BSON::DBRef.new({"$ref" => "collection", "$id" => "id"})
BSON::DBRef.new({"$ref" => "collection", "$id" => "id", "database" => "db"})

注意

BSON::DBRef 构造函数将验证给定的哈希,如果它不是有效的 DBRef,则将引发 ArgumentError。如果给定了无效的 DBRef,则 BSON::ExtJSON.parse_objHash.from_bson 不会引发错误,并将解析 Hash 或反序列化 BSON::Document。

注意

所有有效的 DBRefs 都将被反序列化为 BSON::DBRef 实例,否则将反序列化为 BSON::Document 实例。即使从 Hash 类调用,也是如此。

bson = {"$ref" => "collection", "$id" => "id"}.to_bson.to_s
loaded = Hash.from_bson(BSON::ByteBuffer.new(bson))
=> {"$ref"=>"collection", "$id"=>"id"}
loaded.class
=> BSON::DBRef

为了与 MongoDB Ruby 驱动程序 2.17 及更早版本保持向后兼容性,BSON::DBRef 还可以使用遗留驱动程序 API 构造。该 API 已被弃用,将在 bson-ruby 的未来版本中删除。

BSON::DBRef.new("collection", BSON::ObjectId('61eeb760a15d5d0f9f1e401d'))
BSON::DBRef.new("collection", BSON::ObjectId('61eeb760a15d5d0f9f1e401d'), "db")

这是一个Hash的子类,它将所有键存储为字符串,但允许使用符号键访问它们。

BSON::Document[:key, "value"]
BSON::Document.new

注意

所有BSON文档都将反序列化为BSON::Document实例(或BSON::DBRef,如果它们碰巧是有效的DBRef),即使调用来自Hash

bson = {test: 1}.to_bson.to_s
loaded = Hash.from_bson(BSON::ByteBuffer.new(bson))
=> {"test"=>1}
loaded.class
=> BSON::Document

表示在BSON中将始终比其他值比较高的值。

BSON::MaxKey.new

表示在BSON中将始终比其他值比较低的值。

BSON::MinKey.new

表示给定机器上对象的12字节唯一标识符。

BSON::ObjectId.new

表示具有起始和增量值的特殊时间。

BSON::Timestamp.new(5, 30)

表示未提供值的占位符。

BSON::Undefined.new

表示一个128位的基于十进制的浮点数,能够以精确的精度模拟十进制四舍五入。

# Instantiate with a String
BSON::Decimal128.new("1.28")
# Instantiate with a BigDecimal
d = BigDecimal(1.28, 3)
BSON::Decimal128.new(d)

BigDecimal 的 from_bsonto_bson 方法在底层使用相同的 BSON::Decimal128 方法。这导致了对可以序列化为 BSON 以及可以从现有的 decimal128 BSON 值反序列化的 BigDecimal 值施加了一些限制。做出这种改变是因为将 BigDecimal 实例序列化为 BSON::Decimal128 实例,在 MongoDB 中的查询和聚合方面提供了更多的灵活性。对 BigDecimal 施加的限制如下

  • decimal128 的范围和精度有限,而 BigDecimal 在范围和精度方面没有限制。 decimal128 的最大值约为 10^6145,最小值约为 -10^6145,并且有最大34位的精度。

  • decimal128 能够接受有符号的 NaN 值,而 BigDecimal 则不能。所有反序列化到 BigDecimal 实例的有符号 NaN 值都将是无符号的。

  • decimal128 在序列化和反序列化到 BSON 时会保留尾随零。然而,BigDecimal 则不会保留尾随零,因此使用 BigDecimal 可能会导致精度损失。

注意

在 BSON 5.0 中,默认将 decimal128 反序列化为 BigDecimal。为了将 BSON 文档中的 decimal128 值反序列化为 BSON::Decimal128,可以在 from_bson 上设置 mode: :bson 选项。

BSON 规范定义了一种符号类型,允许 Ruby Symbol 值的来回转换(即,Ruby Symbol 被编码成 BSON 符号,BSON 符号被解码成 Ruby Symbol)。然而,由于大多数编程语言没有原生的符号类型,为了促进互操作性,MongoDB 废弃了 BSON 符号类型,并鼓励使用字符串代替。

注意

BSON 中,哈希 总是字符串。非字符串值在用作哈希键时将被转换为字符串。

Hash.from_bson({foo: 'bar'}.to_bson)
# => {"foo"=>"bar"}
Hash.from_bson({1 => 2}.to_bson)
# => {"1"=>2}

默认情况下,BSON 库将 Symbol 哈希值编码为字符串,并将 BSON 符号解码为 Ruby Symbol 值。

{foo: :bar}.to_bson.to_s
# => "\x12\x00\x00\x00\x02foo\x00\x04\x00\x00\x00bar\x00\x00"
# 0x02 is the string type
Hash.from_bson(BSON::ByteBuffer.new("\x12\x00\x00\x00\x02foo\x00\x04\x00\x00\x00bar\x00\x00".force_encoding('BINARY')))
# => {"foo"=>"bar"}
# 0x0E is the symbol type
Hash.from_bson(BSON::ByteBuffer.new("\x12\x00\x00\x00\x0Efoo\x00\x04\x00\x00\x00bar\x00\x00".force_encoding('BINARY')))
# => {"foo"=>:bar}

要强制将 Ruby 符号编码为 BSON 符号,请将 Ruby 符号包裹在 BSON::Symbol::Raw 中。

{foo: BSON::Symbol::Raw.new(:bar)}.to_bson.to_s
# => "\x12\x00\x00\x00\x0Efoo\x00\x04\x00\x00\x00bar\x00\x00"

某些 BSON 类型在 JSON 中有特殊的表示形式。以下是一些示例,当在它们上调用 to_json 时将自动以这种形式序列化。

对象
JSON
BSON::Binary
{ "$binary" : "\x01", "$type" : "md5" }
BSON::Code
{ "$code" : "this.v = 5" }
BSON::CodeWithScope
{ "$code" : "this.v = value", "$scope" : { v => 5 }}
BSON::DBRef
{ "$ref" : "collection", "$id" : { "$oid" : "id" }, "$db" : "database" }
BSON::MaxKey
{ "$maxKey" : 1 }
BSON::MinKey
{ "$minKey" : 1 }
BSON::ObjectId
{ "$oid" : "4e4d66343b39b68407000001" }
BSON::Timestamp
{ "t" : 5, "i" : 30 }
正则表达式
{ "$regex" : "[abc]", "$options" : "i" }

Ruby中的时间可以精确到纳秒。BSON(以及MongoDB)中的时间只能精确到毫秒。当Ruby Time 实例序列化为BSON或扩展JSON时,时间会被四舍五入到最接近的毫秒。

注意

时间始终向下取整。如果时间早于Unix纪元(1970年1月1日00:00:00 UTC),时间的绝对值会增加。

time = Time.utc(1960, 1, 1, 0, 0, 0, 999_999)
time.to_f
# => -315619199.000001
time.floor(3).to_f
# => -315619199.001

注意

从JRuby版本9.2.11.0开始,JRuby将Unix纪元之前的时间向上取整而不是向下取整(点击此处查看详情)。bson-ruby通过这种方式在JRuby上序列化时正确地向下取整时间。

由于这种向下取整,强烈建议应用程序使用整数数学进行所有时间计算,因为浮点计算的精度不足可能会产生意外的结果。

BSON仅支持将时间存储为自Unix纪元以来的秒数。Ruby的DateTime实例可以序列化为BSON,但BSON反序列化时时间将以Time实例返回。

Ruby中的DateTime类支持非格里高利日历。当序列化非格里高利DateTime实例时,它们首先转换为格里高利日历,并将相应日期存储在数据库中。

BSON仅支持将时间存储为自Unix纪元以来的秒数。Ruby的Date实例可以序列化为BSON,但BSON反序列化时时间将以Time实例返回。

序列化Date实例时使用的时间值是UTC中Date所指日期的午夜。

MongoDB和Ruby都提供处理正则表达式的工具,但它们使用不同的正则表达式引擎。以下小节详细说明了Ruby正则表达式和MongoDB正则表达式之间的差异,并描述了如何处理这两种正则表达式。

MongoDB server uses Perl-compatible regular expressions implemented using the PCRE library and Ruby regular expressions are implemented using the Onigmo regular expression engine, which is a fork of Oniguruma. The two regular expression implementations generally provide equivalent functionality but have several important syntax differences, as described below.

不幸的是,没有简单的方法可以将PCRE正则表达式转换为等效的Ruby正则表达式,目前也没有为PCRE提供Ruby绑定。

Ruby和PCRE正则表达式都支持修饰符。在Ruby中,这些也被称为“选项”,而在PCRE中被称为“标志”。Ruby和PCRE中sm修饰符的含义不同

  • Ruby没有s修饰符,相反,Ruby中的m修饰符的功能与PCRE中的s修饰符相同,即让点(.)匹配任何字符,包括换行符。令人困惑的是,Ruby文档将m修饰符称为“启用多行模式”。

  • Ruby始终在PCRE多行模式等价模式下操作,这在PCRE正则表达式中由m修饰符启用。在Ruby中,锚点^始终指向行的开头,而锚点$始终指向行的末尾。

当编写旨在在Ruby和PCRE环境中(包括MongoDB服务器和大多数其他MongoDB驱动程序)使用的正则表达式时(以下称为“可移植正则表达式”),应避免使用锚点^$。以下部分提供了编写可移植正则表达式的解决方案和建议。

在 Ruby 正则表达式中,^ 锚点始终指代行的开头。在 PCRE 正则表达式中,^ 锚点默认指代输入的开头,而 m 标志将其意义更改为行的开头。

Ruby 和 PCRE 正则表达式都支持 \A 锚点,用于指代输入的开头,不受修饰符的影响。

编写可移植的正则表达式时

  • 使用 \A 锚点指代输入的开头。

  • 使用 ^ 锚点指代行的开头(这需要在 PCRE 正则表达式中设置 m 标志)。或者使用以下任意一种构造,这些构造不受修饰符的影响:- (?:\A|(?<=\n))(处理 LF 和 CR+LF 行结束符)- (?:\A|(?<=[\r\n]))(处理 CR、LF 和 CR+LF 行结束符)

在 Ruby 正则表达式中,$ 锚点始终指代行的结尾。在 PCRE 正则表达式中,$ 锚点默认指代输入的结尾,而 m 标志将其意义更改为行的结尾。

Ruby 和 PCRE 正则表达式都支持 \z 锚点,用于指代输入的结尾,不受修饰符的影响。

编写可移植的正则表达式时

  • 使用 \z 锚点指代输入的结尾。

  • 使用 $ 锚点指代行的结尾(这需要在 PCRE 正则表达式中设置 m 标志)。或者使用以下任意一种构造,这些构造不受修饰符的影响:- (?:\z|(?=\n))(处理 LF 和 CR+LF 行结束符)- (?:\z|(?=[\n\n]))(处理 CR、LF 和 CR+LF 行结束符)

由于没有简单的方法可以将PCRE正则表达式转换为等效的Ruby正则表达式,bson-ruby提供了BSON::Regexp::Raw类来保存MongoDB/PCRE正则表达式。本文档中,此类实例称为“BSON正则表达式”。

可以使用正则表达式文本作为字符串和可选的PCRE修饰符创建此类实例。

BSON::Regexp::Raw.new("^b403158")
# => #<BSON::Regexp::Raw:0x000055df63186d78 @pattern="^b403158", @options="">
BSON::Regexp::Raw.new("^Hello.world$", "s")
# => #<BSON::Regexp::Raw:0x000055df6317f028 @pattern="^Hello.world$", @options="s">

BSON::Regexp模块包含在Ruby的Regexp类中,因此可以省略BSON::前缀。

Regexp::Raw.new("^b403158")
# => #<BSON::Regexp::Raw:0x000055df63186d78 @pattern="^b403158", @options="">
Regexp::Raw.new("^Hello.world$", "s")
# => #<BSON::Regexp::Raw:0x000055df6317f028 @pattern="^Hello.world$", @options="s">

要将Ruby正则表达式转换为BSON正则表达式,请按如下方式实例化BSON::Regexp::Raw对象

regexp = /^Hello.world/
bson_regexp = BSON::Regexp::Raw.new(regexp.source, regexp.options)
# => #<BSON::Regexp::Raw:0x000055df62e42d60 @pattern="^Hello.world", @options=0>

注意,BSON::Regexp::Raw构造函数接受Ruby数值选项和PCRE修饰符字符串。

要将BSON正则表达式转换为Ruby正则表达式,请在BSON正则表达式上调用compile方法。

bson_regexp = BSON::Regexp::Raw.new("^hello.world", "s")
bson_regexp.compile
# => /^hello.world/m
bson_regexp = BSON::Regexp::Raw.new("^hello", "")
bson_regexp.compile
# => /^hello.world/
bson_regexp = BSON::Regexp::Raw.new("^hello.world", "m")
bson_regexp.compile
# => /^hello.world/

注意,第一个示例中,将s PCRE修饰符转换为m Ruby修饰符,最后两个示例尽管原始BSON正则表达式有不同的含义,但转换成了相同的正则表达式。

当BSON正则表达式使用不可移植的^$锚时,其转换为Ruby正则表达式可能会改变其含义。

BSON::Regexp::Raw.new("^hello.world", "").compile =~ "42\nhello world"
# => 3

当将Ruby正则表达式转换为BSON正则表达式(例如,作为查询的一部分发送到服务器)时,BSON正则表达式总是具有m修饰符,以反映Ruby正则表达式中的^$锚的行为。

Ruby和BSON正则表达式都实现了to_bson方法,用于序列化为BSON。

regexp_ruby = /^b403158/
# => /^b403158/
regexp_ruby.to_bson
# => #<BSON::ByteBuffer:0x007fcf20ab8028>
_.to_s
# => "^b403158\x00m\x00"
regexp_raw = Regexp::Raw.new("^b403158")
# => #<BSON::Regexp::Raw:0x007fcf21808f98 @pattern="^b403158", @options="">
regexp_raw.to_bson
# => #<BSON::ByteBuffer:0x007fcf213622f0>
_.to_s
# => "^b403158\x00\x00"

RegexpBSON::Regexp::Raw类都实现了从BSON字节缓冲区反序列化正则表达式的from_bson类方法。这两个类的所有方法都返回一个BSON::Regexp::Raw实例,需要使用上面描述的compile方法将其转换为Ruby正则表达式。

byte_buffer = BSON::ByteBuffer.new("^b403158\x00\x00")
regex = Regexp.from_bson(byte_buffer)
# => #<BSON::Regexp::Raw:0x000055df63100d40 @pattern="^b403158", @options="">
regex.pattern
# => "^b403158"
regex.options
# => ""
regex.compile
# => /^b403158/

BSON文档保留键的顺序,因为文档以键值对列表的形式存储。Ruby中的哈希表也保留键的顺序;因此,在将哈希序列化为BSON文档时,以及在将BSON文档反序列化为哈希时,文档中的键的顺序将与哈希中的键的顺序相匹配。

BSON规范允许BSON文档具有重复键,因为文档以键值对列表的形式存储。应用程序应避免生成此类文档,因为当BSON文档包含重复键时,MongoDB服务器的行为是未定义的。

由于Ruby中的散列表不能有重复的键,当将Ruby散列表序列化为BSON文档时,不会生成重复的键。(仍然可以手动创建具有重复键的BSON文档,以及其他一些MongoDB BSON库可能允许创建具有重复键的BSON文档。)

请注意,由于BSON文档中的键始终以字符串形式存储,在Ruby中指定字符串键和符号键时,只保留最后指定的键。

BSON::Document.new(test: 1, 'test' => 2)
=> {"test"=>2}

当加载具有重复键的BSON文档时,重复键的最后一个值会覆盖相同键的先前值。

返回

常见错误