Menu Docs

Tipos de campo

Neste guia, você pode aprender sobre os tipos de campo suportados no Mongoid que você pode usar para definir o esquema para seus documentos MongoDB .

O MongoDB usa tipos BSON para representar os tipos de dados armazenados nos campos do documento . Para usar dados BSON em um aplicação Mongoid, o Mongoid deve converter os tipos BSON em tipos Ruby no tempo de execução. Por exemplo, ao recuperar um documento do banco de dados, o Mongoid traduz um tipo BSON double para usar o tipo Ruby Float. Quando você salva o documento novamente, o Mongoid converte o campo de volta para um BSON double.

Para saber mais sobre como modelar documentos no Mongoid, consulte o guia Incluir o módulo de documentos em seu modelo.

Observação

Modificar a definição de campo em uma classe de modelo não altera nenhum dado armazenado no banco de dados. Para alterar o tipo de dados de um campo no banco de dados, você deve salvar os dados novamente.

Você pode definir nomes de campo e tipos em classes de modelo utilizando as macros field e type. O exemplo seguinte define os campos de uma classe Person :

class Person
include Mongoid::Document
field :name, type: String
field :date_of_birth, type: Date
field :weight, type: Float
end

A lista a seguir fornece os tipos de campo que você pode usar no Mongoid:

  • Array

  • Bson::Binary

  • BigDecimal

  • Mongoid::Boolean ou Boolean

  • Date

  • DateTime

  • Float

  • Hash

  • Integer

  • Object

  • Bson::ObjectId

  • Range

  • Regexp

  • Set

  • String

  • Mongoid::StringifiedSymbol

  • Time

  • ActiveSupport::TimeWithZone

Observação

O Mongoid não suporta BSON::Int64 ou BSON::Int32 como tipos de campo . O Mongoid salva esses valores no banco de dados corretamente, mas quando você recupera os documentos, os campos são retornados como Integer tipos.

Da mesma forma, ao consultar campos com o tipo BSON::Decimal128, o Mongoid retorna os campos como BigDecimal tipos.

Se você não especificar um tipo para um campo, o Mongoid interpretará como o tipo Object padrão. Um campo não especificado pode armazenar valores de qualquer tipo que seja diretamente serializável para BSON. Você pode deixar um campo sem tipo se o campo puder conter tipos diferentes de dados ou se o tipo do valor do campo não for conhecido.

O exemplo seguinte define uma classe Product com um campo não digitado:

class Product
include Mongoid::Document
field :name, type: String
field :properties
end

O tipo do campo properties é Object, mas varia dependendo do tipo de dados armazenados nesse campo. O exemplo seguinte salva dados no campo properties de duas maneiras 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"}

Como o Mongoid não realiza nenhuma conversão de tipo em campos não digitados ao ler do banco de dados, os valores que exigem manuseio especial podem não ser recuperados corretamente como o valor de um campo não digitado. Não armazene os seguintes tipos de dados BSON em campos não digitados:

  • Date: retorna como Time em campos não digitados

  • DateTime: retorna como Time em campos não digitados

  • Range: retorna como Hash em campos não digitados

Você pode armazenar dados Hash em um campo utilizando o tipo Hash. Ao especificar um campo Hash como, certifique-se de seguir as Restrições de Nomenclatura do MongoDB para garantir que os valores sejam armazenados corretamente no banco de dados.

O exemplo seguinte cria uma classe Person e especifica o campo url como um Hash.

class Person
include Mongoid::Document
field :first_name
field :url, type: Hash
end
person = Person.new(url: {'home_page' => 'http://www.homepage.com'})

Você pode armazenar valores como instâncias BSON Time utilizando o valor de campo Time. Time campos são armazenados no zona horário configurado para seu aplicação. Para saber mais sobre como configurar fusos horários, consulte a seção Configuração do fuso horário do guia Configuração do aplicativo.

O exemplo seguinte cria uma classe Voter e especifica que o valor do campo registered_at é um tipo Time:

class Voter
include Mongoid::Document
field :registered_at, type: Time
end
Voter.new(registered_at: Date.today)

Observação

Armazenar um valor Date ou DateTime em um campo especificado como Time converte o valor para Time quando atribuído. Se você armazenar uma string em um campo Time, o Mongoid analisará a string usando o método Time.parse. Para saber mais sobre como o Mongoid converte queries, consulte a seção Conversões de Query do Tipo de Campo do guia Especificar uma Query.

Você pode armazenar os seguintes tipos de valor em um campo especificado como Date:

  • Date: Armazena o valor conforme fornecido.

  • Time: armazena a parte de data do valor no zona horário do valor.

  • DateTime: armazena a parte de data do valor no zona horário do valor.

  • ActiveSupport::TimeWithZone: armazena a parte de data do valor no zona horário do valor.

  • String: armazena a data especificada na string.

  • Integer: pega o valor como se fosse um carimbo de data/hora UTC e o converte no zona horário configurado do seu aplicativo . O Mongoid então armazena a data retirada desse carimbo de data/hora.

  • Float: pega o valor como se fosse um carimbo de data/hora UTC e o converte no zona horário configurado do seu aplicativo . O Mongoid então armazena a data retirada desse carimbo de data/hora.

Como a conversão de Time ou DateTime descarta a parte de tempo, recomendamos converter explicitamente os objetos String, Time e DateTime em Date antes de atribuí-los ao campo.

Observação

Quando um banco de dados contém um valor de string para um campo Date, o driver analisa o valor usando o método Time.parse e, em seguida, descarta a parte de tempo. Time.parse considera que os valores sem fuso horário estão no horário local. Para saber mais sobre como o Mongoid converte queries, consulte a seção Conversões de Query do Tipo de Campo do guia Especificar uma Query.

Quando você atribui um valor a um campo definido como DateTime ou faz uma query nesses campos, o Mongoid converte o valor em um valor UTC Time antes de enviá-lo ao servidor MongoDB . O Mongoid salva o valor com o zona horário incorporado no objeto DateTime . Quando você recupera o valor, o Mongoid converte a hora UTC para o zona horário configurado para seu aplicação.

O exemplo seguinte cria uma classe Ticket e especifica o campo purchased_at como um campo DateTime :

class Ticket
include Mongoid::Document
field :purchased_at, type: DateTime
end

Se você salvar um valor inteiro ou flutuante em um campo DateTime, o valor será tratado como um carimbo de data/hora Unix em UTC. O exemplo seguinte salva um valor inteiro no campo purchased_at :

ticket.purchased_at = 1544803974
ticket.purchased_at
# Outputs: Fri, 14 Dec 2018 16:12:54 +0000

Se você salvar um valor de string em um campo DateTime, o Mongoid salvará o ticket com o zona horário especificado. Se um zona horário não for especificado, o Mongoid salvará o valor usando o fuso horário configurado como padrão para seu aplicação:

ticket.purchased_at = 'Mar 4, 2018 10:00:00 +01:00'
ticket.purchased_at
# Outputs: Sun, 04 Mar 2018 09:00:00 +0000

Para saber mais sobre como configurar fusos horários, consulte a seção Configuração do fuso horário do guia Configuração do aplicativo.

Observação

O Mongoid analisa os valores de string na DateTime usando o método Time.parse, que considera que os valores sem fuso horário estão na hora local.

Você pode incluir campos de carimbo de data/hora em uma classe incluindo o módulo Mongoid::Timestamps ao criar sua classe. Quando você inclui o Mongoid::Timestamps, o Mongoid cria os seguintes campos na sua classe:

  • created_at: armazena a hora em que o documento foi criado.

  • updated_at: armazena a hora em que o documento foi atualizado pela última vez.

O exemplo a seguir cria uma classe Post com campos de carimbo de data/hora:

class Post
include Mongoid::Document
include Mongoid::Timestamps
end

Você também pode optar por incluir somente os campos created_at ou updated_at, incluindo somente os módulos Created ou Updated. O exemplo a seguir cria uma classe Post somente com o campo created_at e uma classe Post somente com o campo updated_at:

class Post
include Mongoid::Document
include Mongoid::Timestamps::Created
end
class Post
include Mongoid::Document
include Mongoid::Timestamps::Updated
end

Você pode reduzir os nomes dos campo do registro de data e hora para c_at e u_at definindo a opção ::Short ao incluir o 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

Você pode desativar a criação do campo de carimbo de data/hora para operações específicas chamando o método timeless na chamada de método. O exemplo a seguir desabilita os registros de data e hora para a operação save:

post.timeless.save

Você pode armazenar expressões regulares em um campo utilizando o tipo Regexp.

Enquanto o MongoDB implementa Expressões regulares compatíveis com Perl (PCRE), o Mongoid usa a biblioteca Onigmo do Ruby. PCRE e Onigmo fornecem funcionalidade geralmente semelhante, mas existem várias diferenças de sintaxe . Por exemplo, Onigmo utiliza \A e \z para corresponder ao início e fim de uma string, enquanto PCRE utiliza ^ e $.

Quando você declara um campo como Regexp, o Mongoid converte expressões regulares Ruby em expressões regulares BSON ao armazenar o resultado em seu banco de dados. O banco de dados retorna o campo como uma instância Bson::Regexp::Raw. Você pode usar o método compile em instâncias do BSON::Regexp::Raw para converter os dados de volta para uma expressão regular Ruby.

O exemplo seguinte cria uma classe Token e especifica o campo pattern como um 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

Converter uma expressão regular BSON em uma expressão regular Ruby pode produzir uma expressão regular diferente da original. Essa diferença se deve às diferenças entre as sintaxes Onigmo e PCRE. Para saber mais sobre expressões regulares no Mongoid, consulte a seção Expressões regulares do guia Especificar uma query.

Você pode usar o tipo BigDecimal para armazenar números com maior precisão. O Mongoid armazena valores BigDecimal de duas maneiras diferentes, dependendo do valor que você definiu para a propriedade de configuração Mongoid.map_big_decimal_to_decimal128 :

  • Se definido como true, o Mongoid armazena BigDecimal valores como valores BSON Decimal128.

  • Se definido como false (padrão), o Mongoid armazena BigDecimal valores como strings.

Considere as seguintes limitações ao configurar a opção Mongoid.map_big_decimal_to_decimal128 para true:

  • Decimal128 tem alcance e precisão limitados. Decimal128 tem um valor máximo de aproximadamente 10^6145 e um mínimo de aproximadamente -10^6145, com um máximo de 34 bits de precisão. Se você estiver armazenando valores fora desses limites, recomendamos armazená-los como strings.

  • Decimal128 aceita valores de NaN assinados, mas BigDecimal não. Recuperar valores de NaN Decimal128 assinados a partir do banco de dados como BigDecimal retorna o valor não assinado.

  • Decimal128 mantém os zeros finais, mas BigDecimal não. Por esse motivo, recuperar valores Decimal128 do banco de dados como BigDecimal pode resultar em uma perda de precisão.

Observação

Quando você configura a opção Mongoid.map_big_decimal_to_decimal128 para false e armazena um BigDecimal em um campo sem tipo, você não pode executar query do campo como um BigDecimal. Como o valor é armazenado como uma string, consultar o campo sem tipo para um valor de BigDecimal não localiza o valor no banco de dados. Para localizar o valor, você deve primeiro converter o valor da query em uma string.

Você pode evitar esse problema especificando o campo como tipo BigDecimal, em vez de não digitado.

Use o tipo de campo StringifiedSymbol para armazenar valores que devem ser expostos como símbolos para aplicativos Ruby. StringifiedSymbol permite que você use símbolos enquanto garante a interoperabilidade com outros drivers. Esse tipo armazena todos os dados no banco de dados como strings e converte as strings em símbolos quando lidas pelo aplicação. Os valores que não podem ser convertidos diretamente em símbolos, como números inteiros e arrays, são convertidos em strings e, em seguida, em símbolos.

O exemplo seguinte define o campo status como StringifiedSymbol e demonstra como o campo é armazenado e retornado:

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

Você pode usar strings ou símbolos para especificar determinados tipos de campo no Mongoid, em vez de usar seus nomes de classe . O exemplo seguinte especifica o campo order_num utilizando o nome da classe , uma string e um 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

A tabela a seguir fornece os tipos de campo que você pode especificar como strings ou símbolos:

Nome da classe
Símbolo
String

Array

:array

"Array"

BigDecimal

:big_decimal

"BigDecimal"

BSON::Binary

:binary

"BSON::Binary"

Mongoid::Boolean

:boolean

"Mongoid::Boolean"

Date

:date

"Date"

DateTime

:date_time

"DateTime"

Float

:float

"Float"

Hash

:hash

"Hash"

Integer

:integer

"Integer"

BSON::ObjectId

:object_id

"BSON::ObjectId"

Range

:range

"Range"

Regexp

:regexp

"Regexp"

Set

:set

"Set"

String

:string

"String"

StringifiedSymbol

:stringified_symbol

"StringifiedSymbol"

Symbol

:symbol

"Symbol"

Time

:time

"Time"

Você pode criar tipos de campo personalizados e definir como o Mongoid os serializa e os desserializa. Para criar um tipo de campo personalizado, defina uma classe que implemente os seguintes métodos:

  • mongoize: pega uma instância do seu tipo personalizado e a converte em um objeto que o MongoDB pode armazenar.

  • demongoize: pega um objeto do MongoDB e o converte em uma instância do seu tipo personalizado.

  • evolve: Pega uma instância do seu tipo personalizado e a converte em um critério que o MongoDB pode usar para fazer query no banco de dados.

O exemplo seguinte cria um tipo de campo personalizado denominado Point e implementa os 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

No exemplo anterior, o mongoize método de instância aceita uma instância do seu objeto de tipo personalizado e o converte em um Array para armazenar no banco de dados. O mongoize método de classe aceita objetos de todos os tipos e os converte em tipos semelhantes que podem ser armazenados no banco de dados. O Mongoid usa o método de classe mongoize quando chama os métodos getter e setter .

O método demongoize converte o valor Array armazenado no tipo Point personalizado. O Mongoid usa esse método quando chama o getter.

O método evolve converte o tipo de Point personalizado em um tipo de Array consultável e converte todos os outros tipos em object. O Mongoid usa esse método quando chama um método que consulta o banco de dados.

Você pode criar um tipo de campo personalizado que salva um valor diferente no banco de dados do valor atribuído no aplicação. Isso pode ser útil para ter valores descritivos no aplicação e, ao mesmo tempo, armazenar valores mais compactos no banco de dados.

O exemplo seguinte cria um tipo de ColorMapping que utiliza o nome da cor no aplicação, mas armazena a cor como um número inteiro no banco de dados:

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!

Você pode instruir o Mongoid a criar campos dinamicamente, incluindo o módulo Mongoid::Attributes::Dynamic em seu modelo. Isso permite que o Mongoid crie campos com base em um hash arbitrário ou com base nos documentos já armazenados no banco de dados.

O exemplo seguinte cria uma classe Person com campos dinâmicos:

class Person
include Mongoid::Document
include Mongoid::Attributes::Dynamic
end

Dica

Você pode especificar campos fixos e campos dinâmicos dentro da mesma classe. Nesse caso, o Mongoid trata todos os atributos para propriedades com definições de campo de acordo com seu tipo de campo e todos os outros atributos como dinâmicos.

Ao usar campos dinâmicos em seu aplicação, você deve inicialmente definir o valor de uma das seguintes maneiras:

  • Passe o hash do atributo para o construtor.

  • Atribua valores usando o método attributes=.

  • Atribua valores usando o método []=.

  • Atribua valores usando o método write_attribute.

  • Trabalhe com valores que já estão presentes no banco de dados.

Se você não definir inicialmente o valor usando uma das opções anteriores, invocar o atributo retornará um NoMethodError.

Tanto o Mongoid quanto a MongoDB Query API reservam o caractere . para separar os nomes de campo em documentos aninhados e o caractere $ no início de uma string para indicar um operador de query. Por esse motivo, você deve evitar usar esses caracteres nos nomes dos campo .

Se seu aplicação exigir o uso desses caracteres, você poderá acessar os campos ligando para o método send. O exemplo seguinte cria uma classe User com campos que contêm caracteres reservados. Em seguida, ele acessa os campos usando o 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

Você também pode acessar estes campos ligando para o método read_attribute.

Importante

Como a atualização e a substituição de campos contendo esses caracteres reservados requer operadores especiais, a chamada de getters e setters nesses campos gera uma exceção InvalidDotDollarAssignment.