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

Asociaciones incrustadas

Las asociaciones en Mongoid permiten crear relaciones entre modelos. En esta guía, aprenderá a usar asociaciones integradas para almacenar diferentes tipos de documentos en la misma colección. Mongoid admite asociaciones integradas con las siguientes macros:

  • embeds_one

  • embeds_many

  • embedded_in

  • recursively_embeds_one

  • recursively_embeds_many

Las siguientes secciones describen cómo emplear estos tipos de asociación.

Para especificar que un modelo de clase contiene un documento incrustado de un tipo de clase diferente, utilice la macro embeds_one en la clase padre y la macro embedded_in en la clase incrustada. El siguiente ejemplo crea una clase Band con una clase Label incrustada:

class Band
include Mongoid::Document
embeds_one :label
end
class Label
include Mongoid::Document
field :name, type: String
embedded_in :band
end

Mongoid almacena los documentos incrustados con la macro embeds_one en el documento principal como un campo con el mismo nombre que la clase incrustada. Los Label documentos anteriores están almacenados en el documento Band, como se muestra en el siguiente ejemplo:

# Band document
{
"_id" : ObjectId("..."),
"label" : {
"_id" : ObjectId("..."),
"name" : "Periphery",
}
}

Puede almacenar el documento incrustado con un nombre diferente utilizando la opción store_as, como se muestra en el siguiente ejemplo:

class Band
include Mongoid::Document
embeds_one :label, store_as: "record_label"
end

Para especificar que un modelo de clase contiene varios documentos incrustados de un tipo de clase diferente, use la macro embeds_many en la clase principal y la macro embedded_in en la clase integrada. El siguiente ejemplo crea una clase Band con varios documentos incrustados del tipo Album:

class Band
include Mongoid::Document
embeds_many :albums
end
class Album
include Mongoid::Document
field :name, type: String
embedded_in :band
end

Mongoid almacena los documentos embebidos con la macro embeds_many en el documento principal como un campo de arreglo con el mismo nombre que la clase embebida. Los documentos Album anteriores se almacenan en el documento Band, como se muestra en el siguiente ejemplo:

{
"_id" : ObjectId("..."),
"albums" : [
{
"_id" : ObjectId("..."),
"name" : "Omega",
}
]
}

Puede almacenar el documento incrustado con un nombre diferente utilizando la opción store_as, como se muestra en el siguiente ejemplo:

class Band
include Mongoid::Document
embeds_many :albums, store_as: "records"
end

Puedes insertar uno o más documentos del mismo tipo en una clase principal utilizando las macros recursively_embeds_one y recursively_embeds_many. Ambas macros proporcionan acccesores para los documentos principal e hijo a través de un método parent_* y un método child_*, donde * representa el nombre de la clase. El siguiente ejemplo crea una clase Band que inserta recursivamente múltiples otros documentos Band para representar múltiples nombres de bandas:

class Band
include Mongoid::Document
field :name, type: String
recursively_embeds_many
end

Puedes acceder a los documentos padre e hijo mediante los métodos parent_band y child_band, como se muestra en el siguiente ejemplo:

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

Se pueden acceder a los documentos incrustados al consultar la colección de la clase superior utilizando la notación de puntos.

El siguiente ejemplo utiliza notación de puntos para query documentos tipo Tour incrustados en una clase Band. El query devuelve documentos que tienen un valor de tours.year de 2000 o superior:

Band.where('tours.year' => {'$gte' => 2000})

Puede utilizar el método de proyección pluck para recuperar documentos incrustados sin recuperar sus documentos parentales asociados, como se muestra en el siguiente ejemplo:

# Get awards for bands that have toured since 2000
Band.where('tours.year' => {'$gte' => 2000}).pluck(:awards)

Puedes usar los métodos de query de Mongoid para realizar coincidencias incrustadas. Esto te permite consultar asociaciones incrustadas de documentos que ya han sido cargados en la aplicación. Mongoid implementa la coincidencia embebida sin enviar consultas al servidor.

Los siguientes operadores del query son compatibles con la coincidencia incrustada:

  • Operadores de comparación

  • Operadores lógicos

  • Operadores del query de Arreglo

  • $exists

  • $mod

  • $type

  • $regex

  • Operadores a nivel de bits

El siguiente ejemplo query el campo tours incrustado de un documento Band cargado utilizando el operador de comparación $gte:

band = Band.where(name: 'Astral Projection').first
tours = band.tours.where(year: {'$gte' => 2000})

La coincidencia integrada en documentos cargados tiene las siguientes limitaciones conocidas:

  • La coincidencia incrustada no está implementada para las siguientes funcionalidades:

    • Consulta de texto

    • Query geoespacial

    • Operadores que ejecutan código JavaScript, como $where

    • Operadores que se implementan a través de otras funcionalidades del servidor, como $expr y $jsonSchema

  • Mongoid expande los argumentos Range a hashes con las condiciones $gte y $lte. Esto puede generar consultas no válidas en algunos casos y provocar una excepción InvalidQuery.

  • Con el operador $regex, no puedes especificar un objeto de expresión regular como patrón a la vez que proporcionas opciones en el campo $options. Solo puedes proporcionar opciones si el patrón de expresión regular es un string.

Por defecto, Mongoid añade un campo _id a los documentos incrustados. Se puede omitir este campo de los documentos incrustados mediante la especificación explícita del campo _id en el modelo y la omisión del valor por defecto. El siguiente ejemplo ordena a Mongoid no agregar un campo _id a la clase Albums:

class Album
include Mongoid::Document
field :name, type: String
field :_id, type: Object
embedded_in :band
end

En la clase Albums anterior, el campo _id no se agrega automáticamente. Sin un valor por defecto, Mongoid no almacena el valor en la base de datos a menos que proporciones uno en tu modelo.

Puede eliminar documentos secundarios de embeds_many asociaciones utilizando uno de los siguientes métodos:

  • clear

  • delete_all

  • destroy_all

El método clear utiliza el operador $unset para remover toda una asociación incrustada del documento principal. El método clear no ejecuta ninguna función de retorno de destroy. El siguiente ejemplo usa el método clear para remover todas las asociaciones incrustadas de la clase Band:

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

El método delete_all utiliza el operador $pullAll para remover documentos en una asociación embebida. delete_all carga la asociación si aún no se ha cargado, y entonces solo remueve los documentos que existen en la aplicación. El método delete_all no ejecuta ninguna función de retorno de destroy. El siguiente ejemplo utiliza el método delete_all para remover todos los documentos Album integrados de la clase Band:

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

El método destroy_all también utiliza el operador operador $pullAll para eliminar documentos en una asociación embebida. También ejecuta cualquier destroy función de retorno que se haya definido en los documentos asociados. El siguiente ejemplo utiliza el método destroy_all para remover todos los documentos Album embebidos de la clase Band:

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

Volver

Asociaciones referenciadas

En esta página