Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Menu Docs
Página inicial do Docs
/ /

Associações incorporadas

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_one

  • embeds_many

  • embedded_in

  • recursively_embeds_one

  • recursively_embeds_many

As seções a seguir descrevem como usar esses tipos de associação.

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

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

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

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:

  • Operadores de comparação

  • Operadores lógicos

  • Operadores de consulta de matriz

  • $exists

  • $mod

  • $type

  • $regex

  • Operadores bit a bit

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:

    • Query de texto

    • Consultas geoespaciais

    • 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 Range para hashes com condições $gte e $lte. Isso pode levar a queries inválidas em alguns casos e gera uma exceção InvalidQuery.

  • 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.

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.

Você pode excluir documentos filhos de associações embeds_many usando um dos seguintes métodos:

  • clear

  • delete_all

  • destroy_all

O clear método utiliza o operador operador $unset para remover uma associação incorporada inteira do documento principal. O método clear não executa nenhuma chamada de resposta destroy. O exemplo a seguir usa o método clear para remover todas as associações incorporadas da classe Band :

band = Band.find(...)
band.tours.clear

O delete_all método utiliza o operador operador $pullAll para remover documentos em uma associação incorporada. delete_all carrega a associação se ela ainda não tiver sido carregada e remove apenas os documentos existentes no aplicação. O método delete_all não executa nenhuma chamada de resposta destroy. O exemplo a seguir usa o método delete_all para remover todos os documentos Album incorporados da classe Band:

band = Band.find(...)
band.tours.delete_all

O destroy_all método também usa o operador $pullAll para remover documentos em uma associação incorporada. Ele também executa quaisquer chamada de resposta destroy definidas nos documentos associados. O exemplo a seguir usa o método destroy_all para remover todos os documentos Album incorporados da classe Band :

band = Band.find(...)
band.tours.destroy_all

Voltar

Associações referenciadas

Nesta página