Overview
En esta guía, podrá conocer los tipos de campos admitidos en Mongoid que puede utilizar para definir el esquema de sus documentos MongoDB.
Usos de MongoDB Tipos BSON para representar los tipos de datos almacenados en los campos del documento. Para usar datos BSON en una aplicación Mongoid, Mongoid debe convertir los tipos BSON a tipos Ruby en tiempo de ejecución. Por ejemplo, al recuperar un documento de la base de datos, Mongoid traduce un BSON.
double Escriba para usar el tipo Ruby Float. Al volver a guardar el documento, Mongoid convierte el campo de nuevo a un BSON double.
Para obtener más información sobre el modelado de documentos en Mongoid, consulte Incluya el módulo de documento en su guía de modelos.
Nota
Modificar la definición de campo en una clase de modelo no modifica los datos almacenados en la base de datos. Para cambiar el tipo de dato de un campo en la base de datos, debe volver a guardar los datos.
Tipos de Campos
Puede definir nombres y tipos de campos en las clases de modelo mediante las macros field y type. El siguiente ejemplo define los campos de una clase Person:
class Person include Mongoid::Document field :name, type: String field :date_of_birth, type: Date field :weight, type: Float end
La siguiente lista proporciona los tipos de campos que puedes usar en Mongoid:
ArrayBson::BinaryBigDecimalMongoid::BooleanorBooleanDateDateTimeFloatHashIntegerObjectBson::ObjectIdRangeRegexpSetStringMongoid::StringifiedSymbolTimeActiveSupport::TimeWithZone
Nota
Mongoid no admite los tipos de campo BSON::Int64 ni BSON::Int32. Mongoid guarda estos valores correctamente en la base de datos, pero al recuperar los documentos, los campos se devuelven como tipos Integer.
De manera similar, al consultar campos con el tipo BSON::Decimal128, Mongoid devuelve los campos como tipos BigDecimal.
Campos sin tipo
Si no especifica un tipo para un campo, Mongoid lo interpreta como el tipo predeterminado Object. Un campo sin tipo puede almacenar valores de cualquier tipo que se puedan serializar directamente en BSON. Puede dejar un campo sin tipo si este puede contener diferentes tipos de datos o si se desconoce el tipo de su valor.
El siguiente ejemplo define una clase Product con un campo sin tipo:
class Product include Mongoid::Document field :name, type: String field :properties end
El tipo del campo properties es Object, pero varía según el tipo de datos almacenados en él. El siguiente ejemplo guarda datos en el campo properties de dos maneras diferentes:
product = Product.new(properties: "color=white,size=large") # properties field saved as String: "color=white,size=large" product = Product.new(properties: {color: "white", size: "large"}) # properties field saved as Object: {:color=>"white", :size=>"large"}
Dado que Mongoid no realiza conversiones de tipo en campos sin tipo al leer de la base de datos, es posible que los valores que requieren un manejo especial no se recuperen correctamente como valor de un campo sin tipo. No almacene los siguientes tipos de datos BSON en campos sin tipo:
Date: Devuelve comoTimeen campos sin tipoDateTime: Devuelve comoTimeen campos sin tipoRange: Devuelve comoHashen campos sin tipo
Picadillo
Puede almacenar Hash datos en un campo usando el Hash tipo. Al especificar un campo Hash como, asegúrese de seguir las restricciones de nomenclatura de MongoDB para garantizar que los valores se almacenen correctamente en la base de datos.
El siguiente ejemplo crea una clase Person y especifica el campo url como Hash.
class Person include Mongoid::Document field :first_name field :url, type: Hash end person = Person.new(url: {'home_page' => 'http://www.homepage.com'})
Tiempo
Puede almacenar valores como Time instancias BSON utilizando el Time valor delTime campo. Los campos se almacenan en la zona horaria configurada para su aplicación. Para obtener más información sobre la configuración de zonas horarias, consulte la sección "Configuración de zona horaria" de la guía de configuración de la aplicación.
El siguiente ejemplo crea una clase Voter y especifica que el valor del campo registered_at es de tipo Time:
class Voter include Mongoid::Document field :registered_at, type: Time end Voter.new(registered_at: Date.today)
Nota
Al almacenar un Date valor o DateTime en un campo especificado como,Time el valor se convierte a Time al asignarse. Si almacena una cadena en un Time campo, Mongoid la analiza mediante el Time.parse método. Para obtener más información sobre cómo Mongoid convierte las consultas,consulte la sección "Conversiones de consultas de tipo de campo" de la guía "Especificar una consulta".
fecha
Puede almacenar los siguientes tipos de valores en un campo especificado como Date:
Date:Almacena el valor tal como se proporciona.Time:Almacena la parte de fecha del valor en la zona horaria del valor.DateTime:Almacena la parte de fecha del valor en la zona horaria del valor.ActiveSupport::TimeWithZone:Almacena la parte de fecha del valor en la zona horaria del valor.String: Almacena la fecha especificada en la string.IntegerToma el valor como si fuera una marca de tiempo UTC y lo convierte a la zona horaria configurada de la aplicación. Mongoid almacena la fecha obtenida de esa marca de tiempo.FloatToma el valor como si fuera una marca de tiempo UTC y lo convierte a la zona horaria configurada de la aplicación. Mongoid almacena la fecha obtenida de esa marca de tiempo.
Dado que al convertir un Time o DateTime se descarta la parte de tiempo, recomendamos convertir explícitamente los objetos String, Time y DateTime a Date antes de asignarlos al campo.
Nota
Cuando una base de datos contiene un valor de cadena para un Date campo, el controlador analiza el valor mediante el Time.parse método y descarta la parte horaria. Time.parse considera que los valores sin zona horaria están en hora local. Para obtener más información sobre cómo Mongoid convierte las consultas, consulte la sección "Conversiones de consultas de tipo de campo" de la guía "Especificar una consulta".
Fecha y hora
Cuando asignes un valor a un campo definido como DateTime o realices una query en estos campos, Mongoid convierte el valor a un valor UTC Time antes de enviarlo al servidor MongoDB. Mongoid guarda el valor con la zona horaria incrustada en el objeto DateTime. Cuando recuperas el valor, Mongoid convierte la hora UTC a la zona horaria configurada para tu aplicación.
El siguiente ejemplo crea una clase Ticket y especifica el campo purchased_at como un campo DateTime:
class Ticket include Mongoid::Document field :purchased_at, type: DateTime end
Si guarda un valor entero o flotante en un campo DateTime, este se considera una marca de tiempo Unix en UTC. El siguiente ejemplo guarda un valor entero en el campo purchased_at:
ticket.purchased_at = 1544803974 ticket.purchased_at # Outputs: Fri, 14 Dec 2018 16:12:54 +0000
Si se guarda un valor de string en un campo DateTime, Mongoid guarda el ticket con la zona horaria especificada. Si no se especifica una zona horaria, Mongoid guarda el valor usando la zona horaria configurada como por defecto para la aplicación:
ticket.purchased_at = 'Mar 4, 2018 10:00:00 +01:00' ticket.purchased_at # Outputs: Sun, 04 Mar 2018 09:00:00 +0000
Para obtener más información sobre cómo configurar zonas horarias, consulte la sección Configuración de zona horaria de la guía de configuración de la aplicación.
Nota
Mongoid analiza los valores de cadena en DateTime utilizando el método Time.parse, que considera que los valores sin zonas horarias están en hora local.
Marcas de tiempo
Puedes incluir campos de marca de tiempo en una clase incluyendo el módulo Mongoid::Timestamps al crearla. Al incluir Mongoid::Timestamps, Mongoid crea los siguientes campos en tu clase:
created_at:Almacena la hora en que se creó el documento.updated_at:Almacena la hora en que se actualizó el documento por última vez.
En el siguiente ejemplo se crea una clase Post con campos de marca de tiempo:
class Post include Mongoid::Document include Mongoid::Timestamps end
También puede optar por incluir solo los campos created_at o updated_at incluyendo solo los módulos Created o Updated. El siguiente ejemplo crea una clase Post con solo el campo created_at y una clase Post con solo el campo updated_at:
class Post include Mongoid::Document include Mongoid::Timestamps::Created end class Post include Mongoid::Document include Mongoid::Timestamps::Updated end
Puede acortar los nombres de los campos de marca de tiempo a c_at y u_at configurando la opción ::Short al incluir el módulo:
class Post include Mongoid::Document include Mongoid::Timestamps::Short # For c_at and u_at. end class Post include Mongoid::Document include Mongoid::Timestamps::Created::Short # For c_at only. end class Post include Mongoid::Document include Mongoid::Timestamps::Updated::Short # For u_at only. end
Puede deshabilitar la creación del campo de marca de tiempo para operaciones específicas llamando al método timeless en la llamada al método. El siguiente ejemplo deshabilita las marcas de tiempo para la operación save:
post.timeless.save
Regexp
Puede almacenar expresiones regulares en un campo utilizando el tipo Regexp.
Mientras MongoDB implementa expresiones regulares compatibles con Perl (PCRE)Mongoid usa la biblioteca Onigmo de Ruby. PCRE y Onigmo ofrecen una funcionalidad similar, pero presentan varias diferencias sintácticas. Por ejemplo, Onigmo usa \A y \z para encontrar el principio y el final de una cadena, mientras que PCRE usa ^ y.$
Al declarar un campo como Regexp, Mongoid convierte las expresiones regulares de Ruby en expresiones regulares BSON al almacenar el resultado en la base de datos. La base de datos devuelve el campo como una instancia Bson::Regexp::Raw. Puede usar el método compile en instancias BSON::Regexp::Raw para convertir los datos de nuevo a una expresión regular de Ruby.
El siguiente ejemplo crea una clase Token y especifica el campo pattern como Regexp:
class Token include Mongoid::Document field :pattern, type: Regexp end token = Token.create!(pattern: /hello.world/m) token.pattern # Outputs: /hello.world/m # Reload the token from the database token.reload token.pattern # Outputs: #<BSON::Regexp::Raw:0x0000555f505e4a20 @pattern="hello.world", @options="ms">
Importante
Convertir una expresión regular BSON en una expresión regular Ruby podría generar una expresión regular diferente a la original. Esta diferencia se debe a las diferencias entre las sintaxis de Onigmo y PCRE. Para obtener más información sobre las expresiones regulares en Mongoid, consulte la sección "Expresiones regulares" de la guía "Especificar una consulta".
Gran decimal
Puede usar el tipo BigDecimal para almacenar números con mayor precisión. Mongoid almacena valores BigDecimal de dos maneras diferentes, según el valor que configure para la propiedad de configuración Mongoid.map_big_decimal_to_decimal128:
Si se establece en
true(predeterminado), Mongoid almacena valoresBigDecimalcomo valores BSONDecimal128.Si se establece en
false, Mongoid almacenaBigDecimalvalores como cadenas.
Tenga en cuenta las siguientes limitaciones al configurar la opción Mongoid.map_big_decimal_to_decimal128 en true:
Decimal128Tiene un rango y una precisión limitados.Decimal128tiene un valor máximo de aproximadamente10^6145y un mínimo de aproximadamente-10^6145, con un máximo de 34 bits de precisión. Si almacena valores que exceden estos límites, le recomendamos almacenarlos como cadenas.Decimal128Acepta valores con signoNaN, peroBigDecimalno. Recuperar valores con signoNaNDecimal128de la base de datos comoBigDecimaldevuelve el valor sin signo.Decimal128Mantiene los ceros finales, peroBigDecimalno. Por ello, recuperar valoresDecimal128de la base de datos comoBigDecimalpodría resultar en una pérdida de precisión.
Nota
Al configurar la opción Mongoid.map_big_decimal_to_decimal128 como false y almacenar un BigDecimal en un campo sin tipo, no se puede consultar el campo como un BigDecimal. Dado que el valor se almacena como una cadena, consultar el campo sin tipo para obtener un valor BigDecimal no lo encuentra en la base de datos. Para encontrarlo, primero debe convertir el valor de la consulta a una cadena.
Puedes evitar este problema especificando el campo como tipo BigDecimal, en lugar de como sin tipo.
Símbolo de cadena
Utilice el tipo de campo StringifiedSymbol para almacenar valores que deben exponerse como símbolos a las aplicaciones Ruby. StringifiedSymbol permite usar símbolos, garantizando la interoperabilidad con otros controladores. Este tipo almacena todos los datos de la base de datos como cadenas y las convierte en símbolos cuando la aplicación los lee. Los valores que no se pueden convertir directamente a símbolos, como enteros y matrices, se convierten en cadenas y luego en símbolos.
El siguiente ejemplo define el campo status como StringifiedSymbol y demuestra cómo se almacena y se devuelve el campo:
class Post include Mongoid::Document field :status, type: StringifiedSymbol end # Save status as a symbol post = Post.new(status: :hello) # status is stored as "hello" on the database, but returned as a Symbol post.status # Outputs: :hello # Save status as a string post = Post.new(status: "hello") # status is stored as "hello" in the database, but returned as a Symbol post.status # Outputs: :hello
Especificar tipos de campo como cadenas o símbolos
Puede usar cadenas o símbolos para especificar ciertos tipos de campos en Mongoid, en lugar de usar sus nombres de clase. El siguiente ejemplo especifica el campo order_num usando el nombre de clase, una cadena y un símbolo:
class Order include Mongoid::Document # Class Name field :order_num, type: Integer # Symbol field :order_num, type: :integer # String field :order_num, type: "integer" end
La siguiente tabla proporciona los tipos de campos que puede especificar como cadenas o símbolos:
Nombre de la clase | Símbolo | String |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Tipos de campos personalizados
Puede crear tipos de campos personalizados y definir cómo Mongoid los serializa y deserializa. Para crear un tipo de campo personalizado, defina una clase que implemente los siguientes métodos:
mongoize:Toma una instancia de su tipo personalizado y la convierte en un objeto que MongoDB puede almacenar.demongoize:Toma un objeto de MongoDB y lo convierte en una instancia de su tipo personalizado.evolve:Toma una instancia de su tipo personalizado y la convierte en un criterio que MongoDB puede usar para consultar la base de datos.
El siguiente ejemplo crea un tipo de campo personalizado llamado Point e implementa los métodos anteriores:
class Point attr_reader :x, :y def initialize(x, y) @x, @y = x, y end # Converts an object of this instance into an array def mongoize [ x, y ] end class << self # Takes any possible object and converts it to how it is # stored in the database. def mongoize(object) case object when Point then object.mongoize when Hash then Point.new(object[:x], object[:y]).mongoize else object end end # Gets the object as it's stored in the database and instantiates # this custom class from it. def demongoize(object) if object.is_a?(Array) && object.length == 2 Point.new(object[0], object[1]) end end # Converts the object supplied to a criteria and converts it # into a queryable form. def evolve(object) case object when Point then object.mongoize else object end end end end
En el ejemplo anterior, el mongoize método de instancia acepta una instancia de su objeto de tipo personalizado y la convierte en un Array para almacenarla en la base de datos. El mongoize método de clase acepta objetos de todos los tipos y los convierte en tipos similares que se pueden almacenar en la base de datos. Mongoid utiliza el mongoize método de clase al llamar a los métodos getter y setter.
El método demongoize convierte el valor Array almacenado al tipo Point personalizado. Mongoid utiliza este método al llamar al getter.
El método evolve convierte el tipo personalizado Point en un tipo consultable Array y convierte todos los demás tipos en object. Mongoid utiliza este método al llamar a un método que consulta la base de datos.
Tipos de campos personalizados fantasma
Puede crear un tipo de campo personalizado que guarde en la base de datos un valor distinto al asignado en la aplicación. Esto puede ser útil para tener valores descriptivos en la aplicación y almacenar valores más compactos en la base de datos.
El siguiente ejemplo crea un tipo ColorMapping que utiliza el nombre del color en la aplicación, pero almacena el color como un entero en la base de datos:
class ColorMapping MAPPING = { 'black' => 0, 'white' => 1, }.freeze INVERSE_MAPPING = MAPPING.invert.freeze class << self def mongoize(object) MAPPING[object] end def demongoize(object) INVERSE_MAPPING[object] end def evolve(object) MAPPING.fetch(object, object) end end end class Profile include Mongoid::Document field :color, type: ColorMapping end profile = Profile.new(color: 'white') profile.color # Outputs: "white" # Sets "color" field to 0 in MongoDB profile.save!
Campos dinámicos
Puedes indicarle a Mongoid que cree campos dinámicamente incluyendo el módulo Mongoid::Attributes::Dynamic en tu modelo. Esto permite a Mongoid crear campos basándose en un hash arbitrario o en los documentos ya almacenados en la base de datos.
El siguiente ejemplo crea una clase Person con campos dinámicos:
class Person include Mongoid::Document include Mongoid::Attributes::Dynamic end
Tip
Se pueden especificar campos fijos y dinámicos dentro de la misma clase. En este caso, Mongoid trata todos los atributos de las propiedades con definiciones de campo según su tipo, y los demás atributos como dinámicos.
Al utilizar campos dinámicos en su aplicación, debe establecer inicialmente el valor de una de las siguientes maneras:
Pasa el atributo hash al constructor.
Asignar valores utilizando el método
attributes=.Asignar valores utilizando el método
[]=.Asignar valores utilizando el método
write_attribute.Trabajar con valores que ya están presentes en la base de datos.
Si no establece inicialmente el valor utilizando una de las opciones anteriores, al invocar el atributo se devuelve un NoMethodError.
Caracteres reservados
Tanto Mongoid como la API de consultas de MongoDB reservan el carácter . para separar los nombres de campo en documentos anidados y el carácter $ al principio de una cadena para indicar un operador de consulta. Por ello, se recomienda evitar el uso de estos caracteres en los nombres de campo.
Si su aplicación requiere el uso de estos caracteres, puede acceder a los campos llamando al método send. El siguiente ejemplo crea una clase User con campos que contienen caracteres reservados. A continuación, accede a los campos mediante el método send:
class User include Mongoid::Document field :"first.last", type: String field :"$_amount", type: Integer end user = User.first user.send(:"first.last") # Outputs: Mike.Trout user.send(:"$_amount") # Outputs: 42650000
También puede acceder a estos campos llamando al método read_attribute.
Importante
Debido a que actualizar y reemplazar campos que contienen estos caracteres reservados requiere operadores especiales, llamar a getters y setters en estos campos genera una excepción InvalidDotDollarAssignment.