Para agentes de IA: hay un índice de documentación disponible en https://www.mongodb.com/es/docs/llms.txt — versiones en markdown de todas las páginas están disponibles agregando .md a cualquier ruta URL.
See how MongoDB 9.0 delivers up to 2x higher throughput.
MongoDB Branding Shape
Register now >
Docs Menu

Relaciones de modelos en Eloquent

Cuando se usa una base de datos relacional, el siguiente ORM almacena los modelos como filas en tablas que corresponden a las clases de modelo. Cuando usas MongoDB, la Integración de Laravel almacena los modelos como documentos en colecciones que corresponden a las clases de modelos.

Para definir una relación, agregue una función a la clase modelo que llame al método de relación correspondiente. Esta función le permite acceder al modelo relacionado como una propiedad dinámica. Una propiedad dinámica te permite acceder al modelo relacionado utilizando la misma sintaxis que utilizas para acceder a una propiedad en el modelo.

Las siguientes secciones describen las relaciones específicas de Laravel Eloquent y MongoDB disponibles en la Integración de Laravel y muestran ejemplos de cómo definirlas y utilizarlas:

Una vez definida una relación, puede calcular recuentos y otros valores agregados para los modelos relacionados, tal como se describe en la sección "Agregar modelos relacionados" de esta guía.

Una relación uno a uno entre modelos consiste en un registro de modelo relacionado con exactamente otro tipo de registro de modelo.

Cuando agregas una relación uno a uno, Eloquent te permite acceder al modelo mediante una propiedad dinámica y almacena el ID del documento del modelo en el modelo relacionado.

En Laravel MongoDB, puedes definir una relación uno a uno utilizando el método hasOne() o el método belongsTo().

Cuando agregas el inverso de la relación usando el método belongsTo(), Eloquent te permite acceder al modelo usando una propiedad dinámica, pero no agrega ningún campo.

Para aprender más sobre relaciones uno a uno, consulta Uno a uno en la documentación de Laravel.

La siguiente clase de ejemplo muestra cómo definir una relación uno-a-uno HasOne entre un modelo Planet y Orbit usando el método hasOne():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\HasOne;
class Planet extends Model
{
protected $connection = 'mongodb';
public function orbit(): HasOne
{
return $this->hasOne(Orbit::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsTo entre Orbit y Planet mediante el método belongsTo():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsTo;
class Orbit extends Model
{
protected $connection = 'mongodb';
public function planet(): BelongsTo
{
return $this->belongsTo(Planet::class);
}
}

El siguiente código de ejemplo muestra cómo instanciar un modelo para cada clase y agregar la relación entre ellas. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$planet = new Planet();
$planet->name = 'Earth';
$planet->diameter_km = 12742;
$planet->save();
$orbit = new Orbit();
$orbit->period = 365.26;
$orbit->direction = 'counterclockwise';
$planet->orbit()->save($orbit);

El siguiente código de ejemplo muestra cómo acceder a los modelos relacionados utilizando las propiedades dinámicas según se definen en las clases de ejemplo:

$planet = Planet::first();
$relatedOrbit = $planet->orbit;
$orbit = Orbit::first();
$relatedPlanet = $orbit->planet;

Una relación de uno a muchos entre modelos consiste en un modelo que es el padre y uno o más registros de modelos secundarios relacionados.

Al añadir un método de relación uno a muchos, Eloquent permite acceder al modelo mediante una propiedad dinámica y almacena el ID de documento del modelo padre en cada documento de modelo secundario.

En Laravel MongoDB, puede definir una relación de uno a muchos añadiendo el método hasMany() en la clase principal y, opcionalmente, el método belongsTo() en la clase secundaria.

Cuando sumas la inversa de la relación usando el método belongsTo(), Eloquent te permite acceder al modelo principal usando una propiedad dinámica sin añadir ningún campo.

Para aprender más sobre las relaciones de uno a muchos, consulta Uno a Muchos en la documentación de Laravel.

La siguiente clase de ejemplo muestra cómo definir una relación HasMany de uno a muchos entre un Planet modelo padre y Moon modelo hijo mediante el método hasMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\HasMany;
class Planet extends Model
{
protected $connection = 'mongodb';
public function moons(): HasMany
{
return $this->hasMany(Moon::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsTo entre un modelo hijo Moon y el modelo padre Planet utilizando el método belongsTo():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsTo;
class Moon extends Model
{
protected $connection = 'mongodb';
public function planet(): BelongsTo
{
return $this->belongsTo(Planet::class);
}
}

El siguiente código de ejemplo muestra cómo instanciar un modelo para cada clase y agregar la relación entre ellas. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$planet = new Planet();
$planet->name = 'Jupiter';
$planet->diameter_km = 142984;
$planet->save();
$moon1 = new Moon();
$moon1->name = 'Ganymede';
$moon1->orbital_period = 7.15;
$moon2 = new Moon();
$moon2->name = 'Europa';
$moon2->orbital_period = 3.55;
$planet->moons()->save($moon1);
$planet->moons()->save($moon2);

El siguiente código de ejemplo muestra cómo acceder a los modelos relacionados utilizando las propiedades dinámicas tal como se define en las clases de ejemplo.

$planet = Planet::first();
$relatedMoons = $planet->moons;
$moon = Moon::first();
$relatedPlanet = $moon->planet;

Una relación de muchos a muchos consiste en una relación entre dos tipos de modelos diferentes en la que, para cada tipo de modelo, una instancia del modelo puede estar relacionada con múltiples instancias del otro tipo.

En Laravel MongoDB, puedes definir una relación de muchos a muchos añadiendo el método belongsToMany() a ambas clases relacionadas.

Cuando defines una relación de muchos a muchos en una base de datos relacional, Laravel crea una tabla intermedia para rastrear las relaciones. Cuando utilizas la Integración de Laravel, se omite la creación de la tabla intermedia y se agregan los IDs de los documentos relacionados a un campo de documento derivado del nombre de la clase del modelo relacionado.

Tip

Dado que la integración de Laravel utiliza un campo de documento en lugar de una tabla pivote, omite el parámetro tabla pivote del constructor belongsToMany() o establécelo como null.

Para obtener más información sobre relaciones muchos a muchos en Laravel, consulte Muchos a muchos en la documentación de Laravel.

La siguiente sección muestra un ejemplo de cómo crear una relación de muchos a muchos entre clases de modelos.

La siguiente clase de ejemplo muestra cómo definir una relación de BelongsToMany muchos a muchos entre un modelo Planet y SpaceExplorer mediante el método belongsToMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsToMany;
class Planet extends Model
{
protected $connection = 'mongodb';
public function visitors(): BelongsToMany
{
return $this->belongsToMany(SpaceExplorer::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsToMany de varios a varios entre los modelos SpaceExplorer y Planet usando el método belongsToMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\BelongsToMany;
class SpaceExplorer extends Model
{
protected $connection = 'mongodb';
public function planetsVisited(): BelongsToMany
{
return $this->belongsToMany(Planet::class);
}
}

El siguiente código de ejemplo muestra cómo instanciar un modelo para cada clase y agregar la relación entre ellas. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$planetEarth = new Planet();
$planetEarth->name = 'Earth';
$planetEarth->save();
$planetMars = new Planet();
$planetMars->name = 'Mars';
$planetMars->save();
$planetJupiter = new Planet();
$planetJupiter->name = 'Jupiter';
$planetJupiter->save();
$explorerTanya = new SpaceExplorer();
$explorerTanya->name = 'Tanya Kirbuk';
$explorerTanya->save();
$explorerMark = new SpaceExplorer();
$explorerMark->name = 'Mark Watney';
$explorerMark->save();
$explorerJeanluc = new SpaceExplorer();
$explorerJeanluc->name = 'Jean-Luc Picard';
$explorerJeanluc->save();
$explorerTanya->planetsVisited()->attach($planetEarth);
$explorerTanya->planetsVisited()->attach($planetJupiter);
$explorerMark->planetsVisited()->attach($planetEarth);
$explorerMark->planetsVisited()->attach($planetMars);
$explorerJeanluc->planetsVisited()->attach($planetEarth);
$explorerJeanluc->planetsVisited()->attach($planetMars);
$explorerJeanluc->planetsVisited()->attach($planetJupiter);

El siguiente código de ejemplo muestra cómo acceder a los modelos relacionados utilizando las propiedades dinámicas tal como se define en las clases de ejemplo.

$planet = Planet::first();
$explorers = $planet->visitors;
$spaceExplorer = SpaceExplorer::first();
$explored = $spaceExplorer->planetsVisited;

En MongoDB, el patrón de documento incrustado añade los datos del modelo relacionado al modelo padre en lugar de mantener referencias de claves externas. Usa este patrón para cumplir uno o más de los siguientes requisitos:

  • Mantener los datos asociados juntos en una sola colección

  • Realizar actualizaciones atómicas en varios campos del documento y los datos asociados

  • Reducir la cantidad de lecturas requeridas para obtener los datos

En Laravel MongoDB, puedes definir documentos incrustados añadiendo uno de los siguientes métodos:

  • embedsOne() para incrustar un solo documento

  • embedsMany() para insertar múltiples documentos

Nota

Estos métodos devuelven colecciones de Eloquent, que difieren de los objetos del generador de consultas.

Cuando accedes a una relación incrustada, la Integración de Laravel devuelve los datos incrustados como objetos sin procesar en lugar de instancias de modelo hidratadas por defecto. Cuando los documentos incrustados se devuelven como objetos sin procesar, se aplican los siguientes comportamientos:

  • El campo id es de tipo ObjectId, no una string.

  • Los campos de fecha son objetos UTCDateTime, no cadenas formateadas.

  • No se aplican conversiones de atributos de modelos, métodos ni la serialización de toArray().

Para recuperar documentos incrustados como instancias hidratadas del modelo, añade el nombre de la relación a la propiedad $with en el modelo principal. Esta propiedad carga automáticamente la relación en cada query para que la Integración de Laravel hidrate los documentos incrustados como instancias de modelos.

El siguiente ejemplo define un modelo User que utiliza $with para cargar su relación incrustada addresses:

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\EmbedsMany;
class User extends Model
{
protected $with = ['addresses'];
public function addresses()
{
return $this->embedsMany(Address::class);
}
}

Debido a que el modelo incluye $with = ['addresses'], la integración de Laravel devuelve las direcciones incrustadas como instancias del modelo Address. El método toArray() serializa el campo id como una string y los campos de fecha como strings formateadas. Todos los elencos y métodos de modelos Address también están disponibles.

Para obtener más información sobre el patrón de documentos incrustados de MongoDB, consulta los siguientes tutoriales de MongoDB Server:

La siguiente sección muestra un ejemplo de cómo utilizar el patrón de documento incrustado.

La siguiente clase de ejemplo muestra cómo definir un EmbedsMany de uno a muchos entre un modelo SpaceShip y Cargo utilizando el método embedsMany():

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
use MongoDB\Laravel\Relations\EmbedsMany;
class SpaceShip extends Model
{
protected $connection = 'mongodb';
protected $with = ['cargo'];
public function cargo(): EmbedsMany
{
return $this->embedsMany(Cargo::class);
}
}

La clase de modelo incrustado omite la definición de relación como se muestra en la siguiente clase de modelo Cargo:

<?php
declare(strict_types=1);
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Cargo extends Model
{
protected $connection = 'mongodb';
}

El siguiente código de ejemplo muestra cómo crear un modelo de SpaceShip e integrar varios modelos de Cargo, y también incluye el documento de MongoDB creado al ejecutar el código. Haz clic en el botón VIEW OUTPUT para ver los datos generados al ejecutar el código:

$spaceship = new SpaceShip();
$spaceship->name = 'The Millenium Falcon';
$spaceship->save();
$cargoSpice = new Cargo();
$cargoSpice->name = 'spice';
$cargoSpice->weight = 50;
$cargoHyperdrive = new Cargo();
$cargoHyperdrive->name = 'hyperdrive';
$cargoHyperdrive->weight = 25;
$spaceship->cargo()->attach($cargoSpice);
$spaceship->cargo()->attach($cargoHyperdrive);

Una relación entre bases de datos cruzadas en Laravel MongoDB es una relación entre modelos almacenados en una base de datos relacional y modelos almacenados en una base de datos MongoDB.

Cuando añades una relación entre bases de datos, Eloquent te permite acceder a los modelos relacionados mediante una propiedad dinámica.

La integración de Laravel admite los siguientes métodos de relación entre bases de datos:

  • hasOne()

  • hasMany()

  • belongsTo()

Para definir una relación entre bases de datos, debe importar el paquete MongoDB\Laravel\Eloquent\HybridRelations en la clase almacenada en la base de datos relacional.

La siguiente sección muestra un ejemplo de cómo definir una relación entre bases de datos.

La siguiente clase de ejemplo muestra cómo definir una relación HasMany entre un modelo SpaceShip almacenado en una base de datos relacional y un modelo Passenger almacenado en una base de datos MongoDB:

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use MongoDB\Laravel\Eloquent\HybridRelations;
class SpaceShip extends Model
{
use HybridRelations;
protected $connection = 'sqlite';
public function passengers(): HasMany
{
return $this->hasMany(Passenger::class);
}
}

La siguiente clase de ejemplo muestra cómo definir la relación inversa BelongsTo entre un modelo Passenger y el modelo Spaceship utilizando el método belongsTo():

<?php
declare(strict_types=1);
namespace App\Models;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use MongoDB\Laravel\Eloquent\Model;
class Passenger extends Model
{
protected $connection = 'mongodb';
public function spaceship(): BelongsTo
{
return $this->belongsTo(SpaceShip::class);
}
}

Tip

Asegúrese de que la llave primaria definida en el esquema de la tabla de su base de datos relacional coincida con la que utiliza su modelo. Para obtener más información sobre llaves primarias y definiciones de esquemas en Laravel, consulta las siguientes páginas en la documentación de Laravel:

El siguiente código de ejemplo muestra cómo crear un modelo SpaceShip en una base de datos MySQL y modelos Passenger relacionados en una base de datos MongoDB, así como los datos creados al ejecutar el código. Haz clic en el botón VIEW OUTPUT para ver los datos creados al ejecutar el código:

$spaceship = new SpaceShip();
$spaceship->id = 1234;
$spaceship->name = 'Nostromo';
$spaceship->save();
$passengerEllen = new Passenger();
$passengerEllen->name = 'Ellen Ripley';
$passengerDwayne = new Passenger();
$passengerDwayne->name = 'Dwayne Hicks';
$spaceship->passengers()->save($passengerEllen);
$spaceship->passengers()->save($passengerDwayne);

Esta sección describe cómo calcular valores agregados para modelos relacionados sin cargarlos. Utilice el método de agregación with...() para calcular el valor agregado al consultar el modelo principal, o utilice el método load...() correspondiente para calcularlo en una instancia de modelo que ya haya recuperado. La siguiente tabla describe estos métodos:

Método de consulta
Método de instancia
Descripción
Valor de retorno si no hay modelos relacionados

withCount()

loadCount()

Cuenta los modelos relacionados

0

withExists()

loadExists()

Indica si existe algún modelo relacionado.

false

withSum()

loadSum()

Agrega los valores del campo especificado a través de los modelos relacionados.

null

withAvg()

loadAvg()

Calcula la media del campo especificado en los modelos relacionados.

null

withMin()

loadMin()

Devuelve el valor más bajo del campo especificado entre los modelos relacionados.

null

withMax()

loadMax()

Devuelve el valor más alto del campo especificado entre los modelos relacionados.

null

Cada método agrega un atributo al modelo principal. El nombre del atributo combina el nombre de la relación, la función de agregación y, para los métodos withSum(), withAvg(), withMin() y withMax(), el nombre del campo. Por ejemplo, withCount('moons') agrega un atributo moons_count. Para establecer un nombre de atributo personalizado, agregue un alias al nombre de la relación, como se muestra en el ejemplo de esta sección.

Tip

Para obtener más información sobre estos métodos, consulte la sección "Agregación de modelos relacionados" en la documentación de Laravel.

Si almacenas modelos relacionados en su propia colección, la integración de Laravel no puede calcular el agregado en la misma consulta que recupera los modelos principales. En su lugar, ejecuta una consulta adicional para cada agregado que solicites y asigna cada resultado al modelo principal al que pertenece. Considera las siguientes alternativas para consultas que deben escalar:

  • Almacena el valor agregado en el documento principal. Por ejemplo, almacena un campo moons_count en cada documento de la colección planets y actualízalo cuando añadas o elimines una luna.

  • Utilice la etapa de agregación $lookup para combinar las colecciones en una sola consulta. Para obtener más información, consulte la guía de Operaciones de agregación.

La integración de Laravel calcula agregados en relaciones incrustadas, como las definidas por los métodos embedsOne() y embedsMany(), a partir del documento padre sin ejecutar una consulta adicional.

La integración de Laravel no admite los siguientes comportamientos de agregación y genera una excepción si se utilizan:

  • Ordenar los resultados de la consulta por un atributo agregado.

  • Agregación de una relación entre bases de datos

  • Agregando una relación MorphTo

  • Aplicar restricciones, incluidos límites, a una relación incrustada.

Este ejemplo utiliza los modelos Planet y Moon definidos en la sección Relación de uno a muchos para recuperar la siguiente información para el primer planeta de la colección:

  • Si el planeta tiene lunas

  • Número de lunas en órbita

  • El período orbital más largo de sus lunas

$planet = Planet::withExists('moons')
->withCount('moons')
->withMax('moons', 'orbital_period')
->first();
echo 'Has moons: ' . ($planet->moons_exists ? 'yes' : 'no') . PHP_EOL;
echo 'Number of moons: ' . $planet->moons_count . PHP_EOL;
echo 'Longest orbital period: ' . $planet->moons_max_orbital_period . PHP_EOL;

El siguiente ejemplo utiliza un alias para almacenar el recuento en un atributo total_moons en lugar del atributo predeterminado moons_count:

$planet = Planet::withCount('moons as total_moons')->first();

El siguiente ejemplo utiliza el método loadCount() para calcular el recuento de una instancia de modelo que el código ya ha recuperado:

$planet = Planet::first();
$planet->loadCount('moons');
echo 'Number of moons: ' . $planet->moons_count . PHP_EOL;