BSON 教程
本页内容
本教程讨论了使用 Ruby BSON 库。
安装
BSON库可以从以下位置安装:Ruby gems手动安装或使用bundler。
手动安装gem:
gem install bson
要使用bundler安装gem,请将以下内容添加到您的gemfile
:
gem 'bson'
BSON库与MRI >= 2.5和JRuby >= 9.2兼容。
与ActiveSupport一起使用
ActiveSupport定义的类,如TimeWithZone,默认不进行序列化,以避免BSON对ActiveSupport的硬依赖。当在也使用ActiveSupport的应用程序中使用BSON时,必须显式地引入ActiveSupport相关的代码
require 'bson' require 'bson/active_support'
BSON 序列化
获取 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_byte
和 put_bytes
方法。它们接受一个字节字符串作为参数,并将此字符串复制到缓冲区中。put_byte
强制要求参数是长度为 1 的字符串;put_bytes
接受任何长度的字符串。字符串可以包含空字节。
buffer.put_byte("\x00") buffer.put_bytes("\xff\xfe\x00\xfd")
注意
put_byte
和 put_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_int32
和 put_int64
方法。请注意,Ruby 整数可以是任意大的;如果要写入的值超出了 32 位或 64 位整数的范围,put_int32
和 put_int64
会引发 RangeError
。
buffer.put_int32(12345) buffer.put_int64(123456789012345)
注意
如果 put_int32
或 put_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核心类包括:Object
,Array
,FalseClass
,Float
,Hash
,Integer
,BigDecimal
,NilClass
,Regexp
,String
,Symbol
(已弃用),Time
,TrueClass
。
除了核心Ruby对象外,BSON还提供了一些特定于规范的专用类型
BSON::Binary
使用 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
。
可以使用 data
和 type
属性从 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>
UUID 方法
要从其 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_uuid
和 to_uuid
方法时,可以显式指定标准表示
binary = BSON::Binary.from_uuid(uuid_str, :standard) binary.to_uuid(:standard)
请注意,:standard
表示只能与子类型为 :uuid
的 Binary 一起使用(不能与 :uuid_old
一起使用)。
旧版UUIDs
存储在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"
BSON::Code
表示JavaScript代码字符串。
BSON::Code.new("this.value = 5;")
BSON::CodeWithScope
注意
自 MongoDB 4.2.1 版本开始,CodeWithScope
类型已被弃用。从 MongoDB 4.4 版本开始,CodeWithScope
将不再支持各种服务器命令和运算符,如 $where
。在使用 MongoDB 4.4 及更高版本时,请使用其他 BSON 类型和其他运算符。
表示包含值哈希的 JavaScript 代码字符串。
BSON::CodeWithScope.new("this.value = age;", age: 5)
BSON::DBRef
这是 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_obj
和 Hash.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")
BSON::Document
这是一个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::MaxKey
表示在BSON中将始终比其他值比较高的值。
BSON::MaxKey.new
BSON::MinKey
表示在BSON中将始终比其他值比较低的值。
BSON::MinKey.new
BSON::ObjectId
表示给定机器上对象的12字节唯一标识符。
BSON::ObjectId.new
BSON::Timestamp
表示具有起始和增量值的特殊时间。
BSON::Timestamp.new(5, 30)
BSON::Undefined
表示未提供值的占位符。
BSON::Undefined.new
BSON::Decimal128
表示一个128位的基于十进制的浮点数,能够以精确的精度模拟十进制四舍五入。
# Instantiate with a String BSON::Decimal128.new("1.28") # Instantiate with a BigDecimal d = BigDecimal(1.28, 3) BSON::Decimal128.new(d)
BSON::Decimal128 与 BigDecimal
BigDecimal 的 from_bson
和 to_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"
JSON 序列化
某些 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上序列化时正确地向下取整时间。
由于这种向下取整,强烈建议应用程序使用整数数学进行所有时间计算,因为浮点计算的精度不足可能会产生意外的结果。
DateTime实例
BSON仅支持将时间存储为自Unix纪元以来的秒数。Ruby的DateTime
实例可以序列化为BSON,但BSON反序列化时时间将以Time
实例返回。
Ruby中的DateTime
类支持非格里高利日历。当序列化非格里高利DateTime
实例时,它们首先转换为格里高利日历,并将相应日期存储在数据库中。
日期实例
BSON仅支持将时间存储为自Unix纪元以来的秒数。Ruby的Date
实例可以序列化为BSON,但BSON反序列化时时间将以Time
实例返回。
序列化Date
实例时使用的时间值是UTC中Date
所指日期的午夜。
正则表达式
MongoDB和Ruby都提供处理正则表达式的工具,但它们使用不同的正则表达式引擎。以下小节详细说明了Ruby正则表达式和MongoDB正则表达式之间的差异,并描述了如何处理这两种正则表达式。
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中s
和m
修饰符的含义不同
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 行结束符)
BSON::Regexp::Raw
类
由于没有简单的方法可以将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"
Regexp
和BSON::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文档时,重复键的最后一个值会覆盖相同键的先前值。