Overview
En esta guía, puede aprender sobre el formato de datos BSON, cómo MongoDB usa BSON para organizar y almacenar datos y cómo instalar la biblioteca BSON independientemente del controlador Ruby.
Formato de datos BSON
BSON, o JSON binario, es el formato de datos que MongoDB utiliza para organizar y almacenar datos. Este formato incluye todos los tipos de estructuras de datos JSON y admite tipos como fechas, enteros de diferentes tamaños (bits32de y 64bit de), ObjectIds y datos binarios. Para obtener una lista completa de los tipos admitidos, consulte Tipos BSON en la documentación del servidor MongoDB.
BSON no es legible, pero puedes usar la biblioteca Ruby BSON para convertirlo a la representación JSON legible. Puedes leer más sobre la relación entre estos formatos en la guía JSON y BSON del sitio web de MongoDB.
Instalar la biblioteca BSON
Puede instalar la biblioteca BSON (bson) de Rubygems manualmente o usando el empaquetador.
Ejecute el siguiente comando para instalar la gema bson:
gem install bson
Para instalar la gema usando bundler, incluya la siguiente línea en el Gemfile de su aplicación:
gem 'bson'
La biblioteca BSON es compatible con MRI v2.5 y posteriores y JRuby v9.2 y posteriores.
Soporte activo
La serialización de las clases definidas en Soporte Activo, como TimeWithZone, no se carga de forma predeterminada para evitar una fuerte dependencia de BSON con Soporte Activo. Al usar BSON en una aplicación que también usa Soporte Activo, debe requerir la compatibilidad del código de Soporte Activo:
require 'bson' require 'bson/active_support'
Serialización BSON
Puede recuperar la representación BSON sin procesar de un objeto Ruby llamando a to_bson en el objeto. El método to_bson devuelve un BSON::ByteBuffer.
El siguiente código demuestra cómo llamar al método to_bson en objetos Ruby:
"Shall I compare thee to a summer's day".to_bson 1024.to_bson
Puede generar un objeto Ruby a partir de BSON llamando a from_bson en la clase que desea instanciar y pasándole una instancia BSON::ByteBuffer:
String.from_bson(byte_buffer) BSON::Int32.from_bson(byte_buffer)
Búferes de bytes
bson v4.0 introduce el uso de buffers de bytes nativos en MRI y JRuby en lugar de usar StringIO para mejorar el rendimiento.
Escribir en un búfer de bytes
Para crear un ByteBuffer para escribir, instancia un BSON::ByteBuffer sin argumentos:
buffer = BSON::ByteBuffer.new
Bytes sin procesar
Para escribir bytes sin procesar en el búfer de bytes sin transformaciones, utilice los métodos put_byte y put_bytes. Cada método toma una cadena de bytes como argumento y la copia en el búfer. El método put_byte exige que el argumento sea una cadena de longitud 1. put_bytes acepta cadenas de cualquier longitud. Las cadenas pueden contener bytes nulos.
El siguiente código demuestra cómo escribir bytes sin procesar en un búfer de bytes:
buffer.put_byte("\x00") buffer.put_bytes("\xff\xfe\x00\xfd")
Nota
put_byte y put_bytes no escriben un byte de tipo BSON en el búfer antes de escribir la cadena de bytes. Esto significa que el búfer no contiene información sobre el tipo de datos que codifica la cadena de bytes sin procesar.
Métodos de escritura de bytes tipificados
Los métodos de escritura descritos en las siguientes secciones escriben objetos de tipos específicos en la especificación BSON. El tipo indicado por el nombre del método prevalece sobre el tipo del argumento. Por ejemplo, si se pasa un valor de punto put_int32 flotante a, se convierte a un entero y el controlador escribe el entero resultante en el búfer de bytes.
Instrumentos de cuerda
Para escribir una cadena UTF-8 (tipo BSON 0x02) en el búfer de bytes, utilice el método put_string:
buffer.put_string("hello, world")
Las cadenas BSON siempre se codifican en UTF-8. Esto significa que el argumento de put_string debe estar en UTF-8 o en una codificación convertible a UTF-8 (no binaria). Si el argumento está en una codificación distinta a UTF-8, la cadena se convierte primero a UTF-8 y, a continuación, se escribe en el búfer la versión codificada en UTF-8. La cadena debe ser válida en su codificación especificada. Puede contener bytes nulos.
La especificación BSON también define un tipo CString, que se utiliza, por ejemplo, para claves de documentos. Para guardar CStrings en el buffer, utiliza put_cstring:
buffer.put_cstring("hello, world")
Al igual que con las cadenas regulares, las CStrings en BSON deben estar codificadas en UTF-8. Si el argumento no se encuentra en UTF-8, será convertido a UTF-8 y la string resultante se escribirá en el buffer. A diferencia de put_string, la codificación UTF-8 del argumento proporcionado a put_cstring no puede contener ningún byte nulo, ya que el formato de serialización CString en BSON está terminado en nulo.
A diferencia de put_string, put_cstring también acepta símbolos y enteros. En todos los casos, el argumento se convierte en cadena antes de ser escrito en el búfer:
buffer.put_cstring(:hello) buffer.put_cstring(42)
Números
Para escribir un entero de 32o 64bits en el búfer de bytes, utilice los métodos put_int32 y put_int64, respectivamente. Tenga en cuenta que los enteros de Ruby pueden ser arbitrariamente grandes; si el valor que se escribe excede el rango de un entero de 32o 64bits, put_int32 y put_int64 generan un error RangeError.
El siguiente código demuestra cómo escribir valores enteros en un búfer de bytes:
buffer.put_int32(12345) buffer.put_int64(123456789012345)
Nota
Si se dan argumentos de punto flotante a put_int32 o put_int64, los argumentos primero se convierten en números enteros y los números enteros se escriben en el búfer de bytes.
Para escribir un valor de punto flotante de 64bits en el búfer de bytes, utilice put_double:
buffer.put_double(3.14159)
Convertir bytes en cadenas
Para recuperar los datos serializados como una cadena de bytes, llama a to_s en el buffer:
buffer = BSON::ByteBuffer.new buffer.put_string('testing') socket.write(buffer.to_s)
Nota
ByteBuffer Registra las posiciones de lectura y escritura por separado. No es posible rebobinar el búfer para escribir. El método rewind solo afecta la posición de lectura.
Leer desde un búfer de bytes
Para crear un ByteBuffer para leer o deserializar desde BSON, cree una instancia de BSON::ByteBuffer con una cadena de bytes como argumento:
buffer = BSON::ByteBuffer.new(string)
Puede leer desde el búfer utilizando los siguientes métodos que corresponden a diferentes tipos de datos:
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
Para reiniciar la lectura desde el principio de un búfer, utilice rewind:
buffer.rewind
Nota
ByteBuffer Realiza un seguimiento de las posiciones de lectura y escritura por separado. El método rewind solo afecta la posición de lectura.
Clases compatibles
La siguiente lista proporciona las clases Ruby que tienen representaciones en la especificación BSON y tienen un método to_bson definido:
ObjectArrayFalseClassFloatHashIntegerBigDecimalNilClassRegexpStringSymbol(deprecated)TimeTrueClass
Además de los objetos principales de Ruby, BSON también proporciona algunos tipos especiales específicos de la especificación. Las siguientes secciones describen otros tipos compatibles con el controlador.
BSON::Binario
Utilice objetos BSON::Binary para almacenar datos binarios arbitrarios. Puede construir objetos Binary a partir de cadenas binarias, como se muestra en el siguiente código:
BSON::Binary.new("binary_string") # => <BSON::Binary:0x47113101192900 type=generic data=0x62696e6172795f73...>
De forma predeterminada, los objetos Binary se crean con el subtipo binario BSON 0 (:generic). Puede especificar explícitamente el subtipo para indicar que los bytes codifican un tipo de datos específico:
BSON::Binary.new("binary_string", :user) # => <BSON::Binary:0x47113101225420 type=user data=0x62696e6172795f73...>
La siguiente lista proporciona las especificaciones de subtipos válidas:
:generic:function:old:uuid_old:uuid:md5:ciphertext:column:sensitive:vector:user
Puede utilizar los atributos data y type para recuperar los datos y el subtipo de un objeto Binary, como se muestra en el siguiente código:
binary = BSON::Binary.new("binary_string", :user) binary.data # => "binary_string" binary.type # => :user
Puede comparar Binary objetos con el <=> operador, que permite ordenar objetos con el mismo subtipo binario. Para comparar Binary objetos, asegúrese de instalar5.0.2 la versión 7100 o posterior de la biblioteca BSON.
Nota
Codificación BINARIA
BSON::Binary Los objetos siempre almacenan los datos en codificación BINARY, independientemente de la codificación de la cadena pasada al constructor:
str = "binary_string" str.encoding # => #<Encoding:US-ASCII> binary = BSON::Binary.new(str) binary.data # => "binary_string" binary.data.encoding # => #<Encoding:ASCII-8BIT>
Métodos UUID
Para crear un UUID BSON::Binary (subtipo binario 4) a partir de su representación de cadena compatible con RFC 4122, utilice el método from_uuid:
uuid_str = "00112233-4455-6677-8899-aabbccddeeff" BSON::Binary.from_uuid(uuid_str) # => <BSON::Binary:0x46986653612880 type=uuid data=0x0011223344556677...>
Para convertir un UUID BSON::Binary en una representación compatible con RFC 4122, utilice el método 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"
Puede especificar explícitamente la representación UUID estándar en los métodos from_uuid y to_uuid:
binary = BSON::Binary.from_uuid(uuid_str, :standard) binary.to_uuid(:standard)
Puede utilizar la representación :standard solo con un valor Binary del subtipo :uuid, no :uuid_old.
UUIDs heredados
Los datos almacenados en objetos BSON::Binary de subtipo 3 (:uuid_old) pueden persistirse en alguno de los tres diferentes órdenes de bytes, dependiendo del controlador que los creó. Los órdenes de bytes son heredado de CSharp, heredado de Java y heredado de Python. El orden de bytes heredado de Python es el mismo que el orden de bytes estándar de la RFC 4122. Los órdenes de bytes heredados de CSharp y Java tienen algunos bytes en ubicaciones diferentes.
El Binary objeto que contiene un UUID heredado no codifica el formato en el que se almacena dicho UUID. Por lo tanto, los métodos que convierten al formato UUID heredado y viceversa toman el formato o representación deseado como argumento. Una aplicación puede copiar Binary objetos UUID heredados sin saber en qué orden de bytes almacenan sus datos.
Los siguientes métodos para trabajar con UUID heredados se proporcionan para la interoperabilidad con implementaciones existentes que almacenan datos en formatos UUID heredados. En aplicaciones nuevas, utilice únicamente el formato :uuid (subtipo 4), que cumple con la RFC 4122.
Para convertir un UUID heredado BSON::Binary en una cadena, utilice el método to_uuid y especifique la representación deseada. Las representaciones aceptadas son :csharp_legacy, :java_legacy y :python_legacy. Un UUID heredado BSON::Binary no se puede convertir en una cadena sin especificar una representación.
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"
Para crear un UUID heredado BSON::Binary a partir de la representación de cadena del UUID, utilice el método from_uuid y especifique la representación deseada:
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...>
Puede utilizar estos métodos para convertir de una representación a otra:
BSON::Binary.from_uuid('77665544-3322-1100-ffeeddccbbaa9988',:java_legacy).to_uuid(:csharp_legacy) # => "33221100-5544-7766-8899aabbccddeeff"
BSON::Vector
A partir de bson v5.1, puede utilizar el tipo BSON::Vector para representar vectores de valores numéricos.
Puede crear un objeto BSON::Vector para almacenar valores de los siguientes tipos:
int8float32packed_bit
Puede utilizar los atributos opcionales dtype y padding para especificar el tipo de datos del vector y el relleno de bits, respectivamente. BSON::Vector en sí es un contenedor para guardar los valores de la matriz, la información de tipo y la especificación de relleno. Los objetos BSON::Vector se serializan como matrices normales en MongoDB.
El siguiente ejemplo demuestra cómo crear un objeto BSON::Vector:
BSON::Vector.new([ -0.0016261312, -0.028070757, -0.011342932 ], :float32)
Convertir vectores a binario
Puede convertir BSON::Vector objetos y array en objetos BSON::Binary para que se serialicen como instancias de vector binario BSON 9 (subtipo). Utilice el BSON::Binary.from_vector método, como se muestra en el siguiente código:
vector = BSON::Vector.new([ -0.0016261312, -0.028070757, -0.011342932 ], :float32) BSON::Binary.from_vector(vector)
El uso del BSON::Binary tipo mejora la eficiencia del almacenamiento. Para obtener más información, consulte la especificación BSON.
Puedes convertir un BSON::Binary en un BSON::Vector utilizando el método BSON::Binary.as_vector.
Tip
Búsqueda vectorial de MongoDB
Para ver un ejemplo que aprovecha el tipo BSON::Binary para realizar consultas de búsqueda vectorial de MongoDB eficientes, consulte Ejemplos de consultas de búsqueda de MongoDB.
BSON::Código
Este tipo representa una cadena de código JavaScript:
BSON::Code.new("this.value = 5;")
BSON::DBRef
Esta es una subclase de BSON::Document que proporciona accesores para la colección, el identificador y la base de datos de DBRef.
BSON::DBRef.new({"$ref" => "collection", "$id" => "id"}) BSON::DBRef.new({"$ref" => "collection", "$id" => "id", "database" => "db"})
Nota
El constructor BSON::DBRef valida el hash dado y genera un ArgumentError si no es un DBRef válido. Los métodos BSON::ExtJSON.parse_obj y Hash.from_bson no generan un error si se pasa un DBRef no válido y, en su lugar, analizan un Hash o deserializan un BSON::Document.
Nota
Todos los documentos BSON se deserializan en instancias de BSON::DBRef si son instancias válidas de DBRef; de lo contrario, se deserializan en instancias de BSON::Document. Esto se cumple incluso cuando la invocación se realiza desde la clase 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
BSON::Documento
BSON::Document es una subclase de Hash que almacena todas las claves como cadenas, pero permite el acceso a ellas mediante claves de símbolos.
BSON::Document[:key, "value"] BSON::Document.new
Nota
Todos los documentos BSON se deserializan en instancias de BSON::Document o BSON::DBRef, si son instancias válidas de DBRef, incluso cuando la invocación se realiza desde la clase 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::MaxKey representa un valor en BSON que siempre se compara con un valor mayor que cualquier otro valor:
BSON::MaxKey.new
BSON::MinKey
BSON::MinKey representa un valor en BSON que siempre se compara con un valor inferior a cualquier otro valor:
BSON::MinKey.new
BSON::Id. de objeto
BSON::ObjectId representa un identificador único de 12 bytes para un objeto:
BSON::ObjectId.new
BSON::Marca de tiempo
BSON::Timestamp representa un tiempo con un valor de inicio y de incremento:
BSON::Timestamp.new(5, 30)
BSON::Undefined
BSON::Undefined representa un marcador de posición para un valor que no está definido:
BSON::Undefined.new
BSON::Decimal128
BSON::Decimal128 representa un valor de punto flotante basado en decimales de 128bits que puede emular el redondeo decimal con precisión exacta:
# Instantiate with a String BSON::Decimal128.new("1.28") # Instantiate with a BigDecimal d = BigDecimal(1.28, 3) BSON::Decimal128.new(d)
BSON::Decimal128 y BigDecimal
Los métodos BigDecimal#from_bson y BigDecimal#to_bson utilizan internamente los métodos equivalentes BSON::Decimal128. Esto conlleva ciertas limitaciones en los valores BigDecimal que se pueden serializar a BSON y en aquellos que se pueden deserializar a partir de valores BSON decimal128 existentes.
Serializar instancias BigDecimal como instancias BSON::Decimal128 ofrece mayor flexibilidad al realizar consultas y agregaciones en MongoDB. La siguiente lista describe las limitaciones de BigDecimal:
Decimal128tiene un rango y precisión limitados, mientras queBigDecimalno tiene restricciones en términos de rango y precisión.Decimal128tiene un valor máximo de aproximadamente10^6145y un valor mínimo de aproximadamente-10^6145, y tiene un máximo de 34 bits de precisión.Decimal128Puede aceptar valores con signoNaN, mientras queBigDecimalno. Todos los valores con signoNaNque se deserializan en instanciasBigDecimalno estarán firmados.Decimal128mantiene los ceros finales al serializar y deserializar desde BSON.BigDecimal, sin embargo, no mantiene los ceros finales y, por lo tanto, el uso deBigDecimalpuede generar una falta de precisión.
Nota
En la librería BSON v5.0, Decimal128 se deserializa en BigDecimal por defecto. Para que los valores de Decimal128 en los documentos BSON se deserialicen en BSON::Decimal128, se puede establecer la opción mode: :bson al llamar a from_bson.
Serialización JSON
Algunos tipos BSON tienen representaciones especiales en JSON. La siguiente tabla describe el comportamiento de serialización de los tipos especificados al llamar a to_json en ellos.
Objeto BSON de Ruby | Representación JSON |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Instancias de tiempo
Los tiempos en Ruby tienen una precisión de nanosegundos. Los tiempos en BSON tienen una precisión de milisegundos. Al serializar instancias de Ruby Time en BSON o JSON extendido, los tiempos se redondean al milisegundo más cercano.
Nota
Los valores de tiempo se redondean a la baja. Si la hora es anterior a la época Unix (enero 1, 1970 00:00:00 UTC), el valor absoluto de la hora aumenta:
time = Time.utc(1960, 1, 1, 0, 0, 0, 999_999) time.to_f # => -315619199.000001 time.floor(3).to_f # => -315619199.001
Debido a este comportamiento de redondeo, recomendamos que realice todos los cálculos de tiempo utilizando matemáticas enteras, ya que la inexactitud de los cálculos de punto flotante puede producir resultados inesperados.
Nota
JRuby 9.2.11.0 redondea los tiempos de época pre-Unix hacia arriba en lugar de hacia abajo. Para obtener más información sobre este comportamiento, consulte el problema de GitHub relacionado. La biblioteca BSON corrige este comportamiento y reduce los tiempos al serializar en JRuby.
Instancias de fecha y hora
BSON permite almacenar valores de tiempo como el número de segundos transcurridos desde la época de Unix. Las instancias de Ruby DateTime se pueden serializar en BSON, pero al deserializarse, los tiempos se devolverán como instancias Time.
La clase DateTime en Ruby soporta calendarios no gregorianos. Cuando las instancias DateTime no-gregorianas son serializadas, primero se convierten al calendario gregoriano, y la fecha respectiva en el calendario gregoriano se almacena en la base de datos.
Instancias de fecha
BSON permite almacenar valores de tiempo como el número de segundos transcurridos desde la época de Unix. Las instancias de Ruby Date se pueden serializar en BSON, pero al deserializarse, los tiempos se devolverán como instancias Time.
Cuando se serializan instancias Date, el valor de tiempo utilizado es la medianoche del Date en UTC.
Expresiones regulares
Tanto MongoDB como Ruby ofrecen compatibilidad con expresiones regulares, pero utilizan motores de expresiones regulares. Las siguientes subsecciones detallan las diferencias entre las expresiones regulares de Ruby y las de MongoDB.
Expresiones regulares de MongoDB
MongoDB utiliza expresiones regulares compatibles con Perl implementadas mediante la biblioteca PCRE.Las expresiones regulares de Ruby se implementan mediante el motor de expresiones regulares Onigmo, una bifurcación de la biblioteca Oniguruma.
Las dos implementaciones de expresiones regulares, generalmente, proporcionan una funcionalidad equivalente, pero tienen varias diferencias de sintaxis importantes, que se describen en las siguientes secciones.
No existe una manera sencilla de convertir programáticamente una expresión regular PCRE en la expresión regular Ruby equivalente, ya que actualmente no existen enlaces Ruby para PCRE.
Opciones, banderas y modificadores
Tanto las expresiones regulares de Ruby como las de PCRE admiten modificadores. Estos también se denominan "opciones" en Ruby y "indicadores" en PCRE. El significado de los modificadores s y m difiere en Ruby y PCRE de las siguientes maneras:
Ruby no tiene el modificador
s. En su lugar, el modificadormde Ruby realiza la misma función que el modificadorsde PCRE: hacer que el punto (.) coincida con cualquier carácter, incluyendo los saltos de línea. La documentación de Ruby menciona el modificadormcomo habilitador del modo multilínea.Ruby siempre opera en el equivalente del modo multilínea de PCRE, habilitado por el modificador
men las expresiones regulares de PCRE. En Ruby, el ancla^siempre se refiere al principio de la línea y el ancla$siempre se refiere al final de la línea.
Al escribir expresiones regulares destinadas a entornos Ruby y PCRE, incluyendo MongoDB Server y la mayoría de los demás controladores de MongoDB, evite usar los anclajes ^ y $. Las siguientes secciones ofrecen soluciones alternativas y recomendaciones para crear expresiones regulares portables que puedan usarse en múltiples contextos.
^ Ancla
En las expresiones regulares de Ruby, el ancla ^ siempre se refiere al principio de la línea. En las expresiones regulares de PCRE, el ancla ^ se refiere al principio de la entrada por defecto, y el indicador m cambia su significado al principio de la línea.
Tanto las expresiones regulares de Ruby como las de PCRE admiten el ancla \A para referirse al principio de la entrada, independientemente de los modificadores. Las siguientes sugerencias permiten escribir expresiones regulares portátiles:
Utilice el ancla
\Apara hacer referencia al comienzo de la entrada.Utilice el ancla
^para referirse al inicio de la línea si activa el indicadormen expresiones regulares de PCRE. Como alternativa, utilice una de las siguientes construcciones, que funcionan independientemente de los modificadores:(?:\A|(?<=\n)): maneja los finales de líneaLFyCR+LF(?:\A|(?<=[\r\n])): maneja los finales de líneaCR,LFyCR+LF
$ Ancla
En las expresiones regulares de Ruby, el ancla $ siempre se refiere al final de la línea. En las expresiones regulares de PCRE, el ancla $ se refiere al final de la entrada por defecto y el indicador m cambia su significado a fin de línea.
Tanto las expresiones regulares de Ruby como de PCRE admiten el ancla \z para hacer referencia al final de la entrada, independientemente de los modificadores.
Las siguientes sugerencias le permiten escribir expresiones regulares portables:
Utilice el ancla
\zpara hacer referencia al final de la entrada.Utilice el ancla
$para referirse al inicio de la línea si activa el indicadormen expresiones regulares de PCRE. Como alternativa, utilice una de las siguientes construcciones, que funcionan independientemente de los modificadores:(?:\z|(?=\n)): maneja los finales de líneaLFyCR+LF(?:\z|(?=[\n\n])): maneja los finales de líneaCR,LFyCR+LF
BSON::Regexp::Sin formato
Dado que no existe una forma sencilla de convertir programáticamente una expresión regular PCRE en la expresión regular Ruby equivalente, la librería BSON proporciona la clase BSON::Regexp::Raw para almacenar expresiones regulares PCRE.
Puede crear instancias BSON::Regexp::Raw utilizando la expresión regular text como una cadena y modificadores PCRE opcionales:
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">
El módulo BSON::Regexp está incluido en la clase Ruby Regexp, de modo que se puede omitir el prefijo 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">
Conversión de expresiones regulares
El siguiente código convierte una expresión regular de Ruby en una instancia 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>
El constructor BSON::Regexp::Raw acepta tanto las opciones numéricas de Ruby como las cadenas modificadoras PCRE.
Para convertir una expresión regular BSON en una expresión regular Ruby, llame al método compile en la expresión regular BSON:
bson_regexp = BSON::Regexp::Raw.new("^hello.world", "s") bson_regexp.compile # => /^hello.world/m bson_regexp = BSON::Regexp::Raw.new("^hello.world", "") bson_regexp.compile # => /^hello.world/ bson_regexp = BSON::Regexp::Raw.new("^hello.world", "m") bson_regexp.compile # => /^hello.world/
El modificador PCRE s se convirtió al modificador Ruby m en el primer ejemplo del código anterior, y los dos últimos ejemplos se convirtieron a la misma expresión regular aunque las expresiones regulares BSON originales tenían significados diferentes.
Cuando una expresión regular BSON utiliza los anclajes no portables ^ y $, su conversión a una expresión regular de Ruby puede cambiar su significado:
BSON::Regexp::Raw.new("^hello.world", "").compile =~ "42\nhello world" # => 3
Cuando una expresión regular de Ruby se convierte en una expresión regular BSON, por ejemplo, como parte de una consulta, la expresión regular BSON siempre tiene el modificador m establecido, lo que refleja el comportamiento de los anclajes ^ y $ en las expresiones regulares de Ruby.
Leer y escribir expresiones regulares
Tanto las expresiones regulares Ruby como BSON implementan el método to_bson para serializar en 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"
Las clases Regexp y BSON::Regexp::Raw implementan el método de la clase from_bson, que deserializa una expresión regular de un búfer de bytes BSON. Los métodos de ambas clases devuelven una instancia BSON::Regexp::Raw que debe convertirse en una expresión regular de Ruby mediante el método compile, como se describe en el código anterior.
El siguiente código demuestra cómo utilizar el método from_bson para deserializar una expresión regular:
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/
Orden de claves
Los documentos BSON conservan el orden de las claves, ya que se almacenan como listas de pares clave-valor. Los hashes en Ruby también conservan el orden de las claves, por lo que el orden de las claves especificadas en la aplicación se conserva al serializar un hash en un documento BSON y al deserializar un documento BSON en un hash.
Llaves duplicadas
La especificación BSON permite que los documentos BSON tengan claves duplicadas, ya que se almacenan como listas de pares clave-valor. Evite crear documentos que contengan claves duplicadas, ya que el comportamiento de MongoDB Server no está definido cuando un documento BSON contiene claves duplicadas.
En Ruby, los hashes no pueden tener claves duplicadas. Al serializar hashes de Ruby en documentos BSON, no se generan claves duplicadas.
Dado que las claves en los documentos BSON siempre se almacenan como cadenas, especificar la misma clave como cadena y un símbolo en Ruby conserva solo la especificación más reciente:
BSON::Document.new(test: 1, 'test' => 2) # => {"test"=>2}
Al cargar un documento BSON con claves duplicadas, el último valor de una clave duplicada sobrescribe los valores anteriores de la misma clave.