Visão geral
Associações no Mongoid permitem criar relacionamentos entre modelos. Neste guia, você pode aprender como associações referenciadas permitem criar um relacionamento entre dois modelos em que um modelo faz referência ao outro. O Mongoid suporta os seguintes tipos de associação referenciados:
has_onehas_manybelongs_tohas_and_belongs_to_many
As seções a seguir descrevem como usar cada um desses tipos de associação.
Tem um
Você pode usar a macro has_one para declarar que os documentos representados por uma classe também contêm um documento representado por uma classe filha separada. O exemplo seguinte cria uma classe Band com um relacionamento has_one com uma classe Studio :
class Band include Mongoid::Document has_one :studio end
Quando você declara uma associação has_one, a classe filha também deve usar a associação belongs_to que referencia a classe pai. O exemplo seguinte mostra a classe Studio referenciada na classe Band anterior:
class Studio include Mongoid::Document belongs_to :band end
Para saber mais sobre a belongs_to macro, consulte a seção Pertence a.
Você pode usar validações para garantir que a classe filho esteja presente em sua classe pai, conforme mostrado no exemplo a seguir:
class Band include Mongoid::Document has_one :studio validates_presence_of :studio end
Para saber mais sobre validações no Mongoid, consulte o guia deValidações do.
Tem muitos
Você pode usar a macro has_many para declarar que os documentos representados por uma classe contêm vários documentos filhos representados por outra classe. O exemplo seguinte cria uma classe Band com um relacionamento has_many com uma classe Members :
class Band include Mongoid::Document has_many :members end
Quando você declara uma associação has_many, a classe filha também deve usar a associação belongs_to que referencia a classe pai. O exemplo seguinte mostra a classe Member referenciada na classe Band anterior:
class Member include Mongoid::Document belongs_to :band end
Para saber mais sobre a belongs_to macro, consulte a seção Pertence a.
Você pode usar validações para garantir que a classe filho esteja presente em sua classe pai, conforme mostrado no exemplo a seguir:
class Band include Mongoid::Document has_many :members validates_presence_of :members end
Para saber mais sobre validações no Mongoid, consulte o guia Validações.
Recuperar informações de associação
Você pode usar o método any? em uma associação has_many para determinar se a associação contém algum documento sem recuperar todo o conjunto de documentos do banco de dados.
O exemplo seguinte utiliza o método any? para determinar se documentos na classe Band contêm quaisquer documentos Members:
band = Band.first band.members.any?
Você também pode usar o método any? com um filtro para localizar documentos que correspondam a um critério especificado, conforme mostrado no exemplo a seguir:
band = Band.first band.members.any? { |member| member.instrument == 'piano' }
Você pode fornecer um nome de classe para o método any? para filtrar os resultados pelo nome da classe. Isso é útil para associações polimórficas:
class Drummer < Member end band = Band.first band.members.any?(Drummer)
Observação
Depois que os dados da classe associada são carregados no Mongoid, as chamadas subsequentes para o método any? não fazem query no banco de dados. Em vez disso, o Mongoid usa os dados que já estão carregados na memória.
Você também pode chamar o método exists? para determinar se há algum documento persistente na associação. O método exists? sempre consulta o banco de dados e verifica somente documentos que foram salvos no banco de dados. O método exists? não permite a filtragem e não aceita nenhum argumento.
O exemplo seguinte utiliza o método exists? para determinar se há algum documento Members persistente na classe Band :
band = Band.create! # Member is not persisted. band.members.build band.members.exists? # Outputs: false # Persist the member band.members.map(&:save!) band.members.exists? # Outputs: true
Pertence a
Use a macro belongs_to para declarar que um documento representado por uma classe é filho de um documento representado por outra classe. Por padrão, o campo _id da classe pai é armazenado na classe filho. O exemplo seguinte cria uma classe Members com uma associação belongs_to para uma classe Band :
class Members include Mongoid::Document belongs_to :band end
Você pode permitir que o Mongoid persista documentos no banco de dados sem armazenar o _id da classe pai associada definindo a opção optional como true, conforme mostrado no exemplo a seguir:
class Members include Mongoid::Document belongs_to :band, optional: true end
Dica
Você pode alterar globalmente o comportamento padrão da associação belongs_to para não exigir sua classe pai definindo a opção de configuração belongs_to_required_by_default como false nas definições de configuração do seu aplicativo.
Você pode especificar uma associação belongs_to em uma classe filha sem especificar uma associação has_one ou has_many correspondente na classe pai. Ao fazer isso, você não pode acessar os campos do documento filho a partir da classe pai, mas pode acessar os campos pai que estão armazenados na classe filho, como o campo _id do pai. No exemplo a seguir , a classe Band não pode acessar a classe Members , mas a classe Members pode acessar a classe Band :
class Band include Mongoid::Document end class Members include Mongoid::Document belongs_to :band end
Para maior clareza, você pode opcionalmente definir a opção inverse_of como nil para indicar que a classe principal não contém uma associação has_one ou has_many com a classe secundária, conforme mostrado no exemplo a seguir:
class Band include Mongoid::Document end class Members include Mongoid::Document belongs_to :band, inverse_of: nil end
Tem e pertence a muitos
Use a macro has_and_belongs_to_many para declarar que um modelo de classe contém uma relacionamento de muitos para muitos com outra classe. Em um relacionamento de muitos para muitos , cada documento em uma classe pode ser associado a vários documentos em outra classe. O exemplo seguinte cria uma classe Band com um relacionamento has_and_belongs_to_many com uma classe Members . Um documento Band pode fazer referência a vários documentos Members e um documento Members pode fazer referência a vários documentos Band.
class Band include Mongoid::Document has_and_belongs_to_many :members end class Members include Mongoid::Document has_and_belongs_to_many :bands end
Quando você declara uma associação has_and_belongs_to_many, ambas as instâncias do modelo armazenam uma lista dos valores _id do documento associado. Você pode definir a opção inverse_of como nil para armazenar os valores _id do documento associado em apenas uma das instâncias do modelo. O exemplo a seguir solicita que o Mongoid armazene os valores _id do documento associado apenas na classe Band :
class Band include Mongoid::Document has_and_belongs_to_many :tags, inverse_of: nil end class Tag include Mongoid::Document end
Dica
Quando você atualiza um documento que tenha uma associação has_and_belongs_to_many, o Mongoid define o campo updated_at do documento atualizado, mas não define o campo updated_at dos documentos associados.
Associações referenciadas pela query
Você pode usar um pipeline de agregação para consultar documentos em associações referenciadas. O pipeline de agregação permite criar queries em várias coleções e manipular dados em um formato especificado. Para saber mais sobre como usar o pipeline de agregação , consulte o Guia de agregação.
Para queries simples, você pode consultar a associação diretamente. Ao consultar diretamente uma coleção, você pode consultar apenas em campos e valores que estão na própria coleção. Você não pode fazer query diretamente de collections associadas à que está consultando.
Por exemplo, considere as seguintes classes Band e Tour:
class Band include Mongoid::Document has_many :tours field :name, type: String end class Tour include Mongoid::Document belongs_to :band field :year, type: Integer end
O exemplo a seguir faz uma query da classe Tour para documentos que têm um valor year de 2000 ou superior e salva o band_id desses documentos. Em seguida, ele faz uma query da classe Band para documentos que tenham esses valores band_id.
band_ids = Tour.where(year: {'$gte' => 2000}).pluck(:band_id) bands = Band.find(band_ids)