Overview
En esta guía, aprenderá a modelar las relaciones entre colecciones en Django MongoDB Backend. Dado que MongoDB es una base de datos de documentos, Django MongoDB Backend proporciona campos de modelo integrados que almacenan datos relacionados en un único documento, en lugar de distribuirlos entre varias colecciones. Django MongoDB Backend también ofrece un campo de matriz 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.
Datos de muestra
Los ejemplos de esta guía definen modelos que representan las siguientes colecciones en la sample_mflix database:
moviesAlmacena información sobre películas.embedded_movies: Extiendemoviescon incrustaciones de gráficos vectorialesusersAlmacena información sobre los espectadores de películas.commentsAlmacena información sobre los comentarios de las películas.
Para obtener más información sobre la base de datos sample_mflix, consulte Consulte el conjunto de datos de ejemplo de Mflix en la documentación de MongoDB Atlas.
Estrategias de desnormalización
Las bases de datos relacionales normalizan los datos en tablas separadas y utilizan uniones para combinar datos relacionados en el momento de la consulta. El modelo de documentos de MongoDB permite incrustar datos relacionados directamente dentro de un documento padre, lo que se conoce como desnormalización. El backend de Django MongoDB admite ambos enfoques, pero recomendamos desnormalizar los datos para un mejor rendimiento.
Para desnormalizar, elija una de las siguientes estrategias:
Modelos relacionados incrustados: Almacene datos relacionados dentro del documento principal utilizando un
EmbeddedModelFieldEmbeddedModelArrayFieldo. Los datos incrustados se almacenan en el mismo documento de MongoDB que el documento principal y se recuperan en una sola operación de lectura.Almacenardatos de matriz: Almacene una lista de valores escalares relacionados directamente en el documento padre utilizando
ArrayFieldun. Los datos de la matriz se recuperan en una sola operación de lectura sin$lookupoperaciones.
Integrar modelos relacionados
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 único progenitor y no se comparten entre varios documentos.
El número de elementos relacionados es limitado y predecible.
Para incrustar datos relacionados, defina una clase de modelo incrustado como una subclase EmbeddedModel de, luego use un EmbeddedModelField para almacenarlo en el modelo padre.
El siguiente ejemplo define un modelo incrustado Director 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 integrados, consulte Almacene los datos del modelo incrustado en la guía Crear modelos.
Almacenar datos de arreglo
Utilice un ArrayField para almacenar una lista de valores escalares relacionados directamente en el documento principal. Los datos del array se almacenan en el mismo documento de MongoDB y se recuperan en una única operación de lectura sin realizar $lookup operaciones. Utilice esta estrategia cuando se cumplan las siguientes condiciones:
Los valores relacionados son escalares simples, como cadenas de caracteres o números enteros.
El tamaño del array es limitado y predecible.
El siguiente ejemplo define un modelo 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 matrices de documentos estructurados en lugar de valores escalares, utilice un EmbeddedModelArrayField. Para obtener más información, consulte la sección «Almacenar datos de matrices de modelos incrustados» en la guía «Crear modelos».
Campos relacionales
Importante
Las consultas a través de campos relacionales utilizan el operador de MongoDB,$lookup que puede ser lento para colecciones grandes. Siempre que sea posible, utilice modelos integrados. Para obtener más información sobre las consideraciones de rendimiento, consulte Limitaciones de rendimiento.
Si sus datos están estructurados de forma similar a una base de datos relacional y necesita modelar grandes conjuntos de datos jerárquicos, puede utilizar los siguientes campos relacionales de Django que vinculan documentos entre colecciones separadas:
Importante
No se pueden utilizar campos relacionales dentro de clases de modelos incrustadas o como el base_field de un ArrayField.
ForeignKey
Utilice un campo para crear una relación de muchos a uno entre dos modelos. Cada documento del modelo que hace referencia se vincula a un documento del modelo referenciado. Pase los siguientes argumentos ForeignKey al ForeignKey() constructor:
to: La clase del modelo a la que enlazaron_delete: El comportamiento de eliminación cuando se elimina el documento referenciado
El siguiente ejemplo vincula un modelo Comment con un modelo Movie mediante un campo ForeignKey. Al eliminar un documento sample_mflix.movies, también se eliminan todos los documentos sample_mflix.comments 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 obtener más información sobre on_delete las opciones, consulte ForeignKey.on_delete en la documentación de Django.
OneToOneField
Utilice un campo para crear una relación uno a uno entre dos modelos. Cada documento del modelo de referencia se vincula con exactamente un documento del modelo referenciado. Pase los siguientes argumentos OneToOneField al OneToOneField() constructor:
to: La clase del modelo a la que enlazaron_delete: El comportamiento 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. Al eliminar un documento sample_mflix.movies, su documento sample_mflix.embedded_movies vinculado también se elimina:
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)
Campo de muchos a muchos
Utilice un campo para crear una relación de muchos a muchos entre dos modelos. Cada documento de cualquiera de los modelos puede vincularse a varios documentos del otro modelo. Pase la clase del modelo al que se vinculará como primer argumento ManyToManyField al ManyToManyField() constructor.
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)
Convertir datos relacionales a datos incrustados
Si ya tienes modelos que usan campos relacionales y quieres mejorar el rendimiento de lectura, puedes convertirlos para que usen modelos incrustados. 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:
ForeignKey, que enlaza conDirectorOneToOneField, que enlaza conAwardManyToManyField, que enlaza conWriter
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, cambie cada modelo relacionado para que extienda EmbeddedModel en lugar de models.Model, luego reemplace los campos relacionales del modelo Movie con los campos incrustados correspondientes:
Reemplaza el
ForeignKeypor unEmbeddedModelField.Reemplaza el
OneToOneFieldpor unEmbeddedModelField.Reemplaza el
ManyToManyFieldpor unEmbeddedModelArrayField.
El siguiente ejemplo muestra el modelo Movie convertido:
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)
Información Adicional
Para aprender a consultar datos en modelos relacionados, consulte Consultas de campos avanzadas en la guía Especificar una consulta.
Para obtener más información sobre los campos relacionales de Django, consulte la referencia de campos del modelo en la documentación de Django.
Para obtener más información sobre los modelos integrados, consulte la sección "Almacenar datos de modelos integrados" en la guía "Crear modelos".