Docs Menu
Docs Home
/ /
/ / /

Relaciones de modelo y desnormalización

En esta guía, puedes aprender a modelar las relaciones entre colecciones en Django MongoDB Backend. Debido a que MongoDB es una base de datos de documentos, Django MongoDB Backend ofrece campos de modelo incrustados que almacenan datos relacionados en un solo documento en lugar de en varias colecciones. El Backend de Django MongoDB también proporciona un campo de arreglo, que permite almacenar una lista de valores escalares relacionados en el documento principal.

Esta guía explica cuándo utilizar cada enfoque y proporciona ejemplos para demostrar las estrategias.

Los ejemplos en esta guía definen modelos que representan las siguientes colecciones en la sample_mflix database:

  • movies: almacena información sobre películas

  • embedded_moviesExtiende movies con incrustaciones de gráficos vectoriales

  • users: Almacena información acerca de los espectadores de películas

  • comments: Almacena información sobre los comentarios de películas

Para obtener más información sobre la base de datos sample_mflix, consulte Conjunto de datos de Mflix de muestra en la documentación de MongoDB Atlas.

Las bases de datos relacionales normalizan los datos en tablas separadas y utilizan uniones para combinar los datos relacionados al momento de la query. El modelo orientado a documentos de MongoDB te permite insertar datos relacionados directamente dentro de un documento padre, lo que se denomina desnormalización. El Backend Django MongoDB es compatible con ambos enfoques, pero recomendamos desnormalizar tus datos para obtener un mejor rendimiento.

Para desnormalizar, elige una de las siguientes estrategias:

  • Insertar Modelos Relacionados: Almacena datos relacionados dentro del documento principal utilizando un EmbeddedModelField o EmbeddedModelArrayField. Los datos incrustados se almacenan en el mismo documento de MongoDB que el elemento primario y se recuperan en una única operación de lectura.

  • Almacenar datos de arreglo: almacene una lista de valores escalares relacionados directamente en el documento principal utilizando un ArrayField. Los datos de arreglos se recuperan en una sola operación de lectura sin operaciones $lookup.

Utilice un modelo integrado cuando se cumplan todas las siguientes condiciones:

  • Los datos relacionados siempre se leen junto con el documento principal.

  • Los datos relacionados pertenecen a un solo padre y no se comparten entre varios documentos.

  • La cantidad de elementos relacionados está limitada y es predecible.

Para integrar datos relacionados, define una clase de modelo incrustado como una subclase de EmbeddedModel, luego utiliza un EmbeddedModelField para almacenarlo en el modelo principal.

El siguiente ejemplo define un modelo Director incrustado y luego define un modelo Movie que almacena una instancia del modelo Director:

from django.db import models
from django_mongodb_backend.models import EmbeddedModel
from django_mongodb_backend.fields import EmbeddedModelField
class Director(EmbeddedModel):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Movie(models.Model):
title = models.CharField(max_length=200)
director = EmbeddedModelField(Director, null=True, blank=True)

Para obtener más información sobre los modelos embebidos, consulta Almacenar datos integrados del modelo en la guía Crear modelos.

Utilice un ArrayField para almacenar una lista de valores escalares relacionados directamente en el documento principal. Los datos de la matriz se almacenan en el mismo documento de MongoDB y se recuperan en una sola operación de lectura sin realizar operaciones $lookup. Utiliza esta estrategia cuando se cumplan las siguientes condiciones:

  • Los valores relacionados son escalares simples, como cadenas o enteros.

  • El tamaño del arreglo está limitado y es predecible.

El siguiente ejemplo define un modelo de Movie que almacena una lista de cadenas en el campo cast:

from django.db import models
from django_mongodb_backend.fields import ArrayField
class Movie(models.Model):
title = models.CharField(max_length=200)
cast = ArrayField(models.CharField(max_length=100), blank=True)

Para almacenar arreglos de documentos estructurados en lugar de valores escalares, utilice un EmbeddedModelArrayField en su lugar. Para obtener más información, consulta almacenar datos de arreglos de modelos integrados en la guía Crear modelos.

Importante

Las consultas entre campos relacionales utilizan el operador $lookup de MongoDB, que puede ser lento para colecciones grandes. Cuando sea posible, utiliza modelos integrados en su lugar. Para aprender más acerca de las consideraciones del rendimiento, consulta Limitaciones del rendimiento.

Si tus datos están estructurados de manera similar a una base de datos relacional y necesitas modelar grandes conjuntos de datos jerárquicos, puedes usar los siguientes campos relacionales de Django que vinculan documentos entre colecciones separadas:

Importante

No se pueden usar campos relacionales dentro de clases de modelo embebidas ni como el base_field de un ArrayField.

Utiliza un campo ForeignKey para crear una relación de muchos a uno entre dos modelos. Cada documento en el modelo de referencia se vincula a un documento en el modelo referenciado. Pasa los siguientes argumentos al constructor ForeignKey():

  • toLa clase de modelo para enlazar

  • on_delete: El comportamiento de eliminación cuando eliminas el documento referenciado

El siguiente ejemplo vincula un modelo Comment a un modelo Movie utilizando un campo ForeignKey. Cuando borras un sample_mflix.movies documento, también se borran todos los sample_mflix.comments documentos relacionados:

from django.db import models
class Movie(models.Model):
title = models.CharField(max_length=200)
class Comment(models.Model):
movie = models.ForeignKey(
Movie,
on_delete=models.CASCADE,
)
text = models.TextField()

Tip

Para aprender más sobre las opciones de on_delete, consulta ForeignKey.on_delete en la documentación de Django.

Usa un campo OneToOneField para crear una relación uno a uno entre dos modelos. Cada documento en el modelo de referencia está vinculado a exactamente un documento en el modelo referenciado. Pase los siguientes argumentos al constructor de OneToOneField():

  • toLa clase de modelo para enlazar

  • on_deleteComportamiento de eliminación cuando se elimina el documento referenciado

El siguiente ejemplo define un modelo EmbeddedMovie que se vincula a un modelo Movie mediante un campo OneToOneField. Cuando eliminas un documento de sample_mflix.movies, también se elimina su documento vinculado de sample_mflix.embedded_movies:

from django.db import models
from django_mongodb_backend.fields import ArrayField
class Movie(models.Model):
title = models.CharField(max_length=200)
class EmbeddedMovie(models.Model):
movie = models.OneToOneField(
Movie,
on_delete=models.CASCADE,
)
plot_embedding = ArrayField(models.FloatField(), blank=True)

Utiliza un campo ManyToManyField para crear una relación de muchos a muchos entre dos modelos. Cada documento en cualquiera de los modelos puede estar vinculado a varios documentos en el otro modelo. Pasa la clase del modelo con la que se va a vincular como el primer argumento en el constructor de ManyToManyField().

El siguiente ejemplo vincula un modelo Viewer con un modelo Movie. Cada espectador puede ver varias películas, y cada película puede ser vista por varios espectadores:

from django.db import models
class Movie(models.Model):
title = models.CharField(max_length=200)
class Viewer(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=200)
watched = models.ManyToManyField(Movie, blank=True)

Si tienes modelos existentes que utilizan campos relacionales y deseas mejorar el rendimiento de lectura, puedes convertirlos para que utilicen modelos embebidos en su lugar. Esto elimina las operaciones $lookup y almacena todos los datos relacionados en un único documento de MongoDB.

Este ejemplo define un modelo Movie que tiene los siguientes campos relacionales:

from django.db import models
class Director(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Award(models.Model):
wins = models.IntegerField(default=0)
nominations = models.IntegerField(default=0)
text = models.CharField(max_length=100)
class Writer(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Movie(models.Model):
title = models.CharField(max_length=200)
director = models.ForeignKey(
Director,
null=True,
on_delete=models.SET_NULL,
)
awards = models.OneToOneField(
Award,
null=True,
on_delete=models.SET_NULL,
)
writers = models.ManyToManyField(Writer, blank=True)

Para convertir estos campos relacionales en campos incrustados, cambia cada modelo relacionado para que extienda EmbeddedModel en lugar de models.Model, luego reemplaza los campos relacionales del modelo Movie por los campos incrustados correspondientes:

  • Sustituya el ForeignKey por un EmbeddedModelField

  • Sustituya el OneToOneField por un EmbeddedModelField

  • Sustituya el ManyToManyField por un EmbeddedModelArrayField

El siguiente ejemplo muestra el modelo convertido Movie:

from django.db import models
from django_mongodb_backend.models import EmbeddedModel
from django_mongodb_backend.fields import (
EmbeddedModelField,
EmbeddedModelArrayField,
)
class Director(EmbeddedModel):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Award(EmbeddedModel):
wins = models.IntegerField(default=0)
nominations = models.IntegerField(default=0)
class Writer(EmbeddedModel):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
class Movie(models.Model):
title = models.CharField(max_length=200)
director = EmbeddedModelField(Director, null=True, blank=True)
awards = EmbeddedModelField(Award, null=True, blank=True)
writers = EmbeddedModelArrayField(Writer, blank=True)

Para aprender a consultar datos entre modelos relacionados, consulta Consultas Avanzadas de Campo en la guía Especificar una consulta.

Para obtener más información sobre los campos relacionales de Django, consulta el Model field reference en la documentación de Django.

Para obtener más información sobre los modelos embebidos, consulta Almacenar datos del modelo embebido en la guía Crear modelos.

Volver

Modelos geoespaciales

En esta página