Visão geral
Associações no Mongoid permitem criar relacionamentos entre modelos. Neste guia, você pode aprender a usar associações incorporadas para armazenar diferentes tipos de documentos na mesma coleção. O Mongoid suporta associações incorporadas com as seguintes macros:
embeds_oneembeds_manyembedded_inrecursively_embeds_onerecursively_embeds_many
As seções a seguir descrevem como usar esses tipos de associação.
Incorpora um
Para especificar que um modelo de classe contém um documento incorporado de um tipo de classe diferente, use a macro embeds_one na classe principal e a macro embedded_in na classe incorporada. O exemplo a seguir cria uma classe Band com uma classe Label incorporada :
class Band include Mongoid::Document embeds_one :label end class Label include Mongoid::Document field :name, type: String embedded_in :band end
O Mongoid armazena documentos incorporados com a macro embeds_one no documento principal como um campo com o mesmo nome da classe incorporada. Os documentos Label anteriores são armazenados no documento Band, conforme mostrado no exemplo a seguir:
# Band document { "_id" : ObjectId("..."), "label" : { "_id" : ObjectId("..."), "name" : "Periphery", } }
Você pode armazenar o documento incorporado com um nome diferente usando a opção store_as, conforme mostrado no exemplo a seguir:
class Band include Mongoid::Document embeds_one :label, store_as: "record_label" end
Incorpora muitos
Para especificar que um modelo de classe contém vários documentos incorporados de um tipo de classe diferente, use a macro embeds_many na classe principal e a macro embedded_in na classe incorporada. O exemplo a seguir cria uma classe Band com vários documentos do tipo Album incorporados:
class Band include Mongoid::Document embeds_many :albums end class Album include Mongoid::Document field :name, type: String embedded_in :band end
O Mongoid armazena documentos incorporados com a macro embeds_many no documento principal como um campo de array com o mesmo nome da classe incorporada. Os documentos Album anteriores são armazenados no documento Band, conforme mostrado no exemplo a seguir:
{ "_id" : ObjectId("..."), "albums" : [ { "_id" : ObjectId("..."), "name" : "Omega", } ] }
Você pode armazenar o documento incorporado com um nome diferente usando a opção store_as, conforme mostrado no exemplo a seguir:
class Band include Mongoid::Document embeds_many :albums, store_as: "records" end
Incorporação recursiva
Você pode incorporar um ou mais documentos do mesmo tipo em uma classe principal usando as macros recursively_embeds_one e recursively_embeds_many. Ambas as macros fornecem acessadores para os documentos pai e filho por meio de um método parent_* e um método child_*, em que * representa o nome da classe. O exemplo a seguir cria uma classe Band que incorpora recursivamente vários outros documentos Band para representar vários nomes de bandas:
class Band include Mongoid::Document field :name, type: String recursively_embeds_many end
Você pode acessar os documentos principal e secundário por meio dos métodos parent_band e child_band, conforme mostrado no exemplo a seguir:
root = Band.new(name: "Linkin Park") # Add child bands child_one = root.child_band.build(name: "Lincoln Park") child_two = root.child_band.build(name: "Xero") # Access parent band child_one.parent_band # Outputs: root
Associações incorporadas à consulta
Você pode acessar documentos incorporados ao consultar a collection da classe principal usando a notação de ponto.
O exemplo a seguir usa notação de ponto para consultar documentos do tipo Tour que estão incorporados em uma classe Band . A query retorna documentos com um valor tours.year de 2000 ou superior:
Band.where('tours.year' => {'$gte' => 2000})
Você pode usar o método de projeção pluck para recuperar documentos incorporados sem recuperar seus documentos pai associados, conforme mostrado no exemplo a seguir:
# Get awards for bands that have toured since 2000 Band.where('tours.year' => {'$gte' => 2000}).pluck(:awards)
Você pode usar os métodos de query do Mongoid para realizar a correspondência incorporada, o que permite consultar associações incorporadas de documentos que já estão carregados no aplicação. O Mongoid implementa a correspondência incorporada sem enviar queries para o servidor.
Os seguintes operadores de query são compatíveis com correspondência incorporada:
O exemplo a seguir consulta o campo tours incorporado de um documento Band carregado usando o operador de comparação $gte:
band = Band.where(name: 'Astral Projection').first tours = band.tours.where(year: {'$gte' => 2000})
A correspondência incorporada em documentos carregados tem as seguintes limitações conhecidas:
A correspondência incorporada não está implementada para as seguintes funcionalidades:
Operadores que executam código JavaScript, como $where
Operadores implementados por meio de outras funcionalidades do servidor , como $expr e $jsonSchema
O Mongoid expande os argumentos
Rangepara hashes com condições$gtee$lte. Isso pode levar a queries inválidas em alguns casos e gera uma exceçãoInvalidQuery.Com o operador
$regex, você não pode especificar um objeto de expressão regular como um padrão e, ao mesmo tempo, fornecer opções para o campo$options. Você só pode fornecer opções se o padrão de expressão regular for uma string.
Omitir campos _id
Por padrão, o Mongoid adiciona um campo _id aos documentos incorporados. Você pode omitir esse campo de documentos incorporados especificando explicitamente o campo _id em seu modelo e omitindo o valor padrão. O exemplo a seguir instrui o Mongoid a não adicionar um campo _id à classe Albums :
class Album include Mongoid::Document field :name, type: String field :_id, type: Object embedded_in :band end
Na classe Albums anterior, o campo _id não é adicionado automaticamente. Sem um valor padrão, o Mongoid não armazena o valor no banco de dados, a menos que você forneça um em seu modelo.
Excluir associações incorporadas
Você pode excluir documentos filhos de associações embeds_many usando um dos seguintes métodos:
cleardelete_alldestroy_all
The clear method uses the $unset operator operator to remove an entire embedded association from the parent document. The clear method does not run any destroy callbacks. The following example uses the clear method to remove all embedded associations from the Band class:
band = Band.find(...) band.tours.clear
The delete_all method uses the $pullAll operator operator to remove documents in an embedded association. delete_all loads the association if it has not yet been loaded, then only removes the documents that exist in the application. The delete_all method does not run any destroy callbacks. The following example uses the delete_all method to remove all embedded Album documents from the Band class:
band = Band.find(...) band.tours.delete_all
The destroy_all method also uses the $pullAll operator operator to remove documents in an embedded association. It also runs any destroy callbacks that are defined on the associated documents. The following example uses the destroy_all method to remove all embedded Album documents from the Band class:
band = Band.find(...) band.tours.destroy_all