Overview
Las operaciones$lookupunen datos de dos colecciones de la misma base de datos según un campo específico. Las operaciones$lookuppueden ser útiles cuando los datos tienen una estructura similar a la de una base de datos relacional y se necesita modelar grandes conjuntos de datos jerárquicos. Sin embargo, estas operaciones pueden ser lentas y consumir muchos recursos, ya que necesitan leer y ejecutar lógica en dos colecciones en lugar de una sola.
Si ejecutas con frecuencia operaciones $lookup, considera reestructurar tu esquema de modo que tu aplicación pueda query una única colección para obtener toda la información que necesita. Puedes utilizar el modelo de esquema flexible de MongoDB con documentos incrustados y arreglos para captar las relaciones entre los datos en una única estructura de documento. Utiliza este modelo desnormalizado para aprovechar los útiles documentos de MongoDB y permitir que tu aplicación recupere y manipule datos relacionados en una sola query.
Ejemplos
Los siguientes ejemplos muestran dos estructuras de esquema diseñadas para reducir $lookup operaciones:
Usar Documentos Incrustados
Considere el siguiente ejemplo: una tienda de comestibles registra la información nutricional y de inventario individualmente en dos colecciones separadas. Cada artículo del inventario corresponde a un artículo único de información nutricional. El campo nutrition_id vincula la colección inventory con la colección nutrition_facts, de forma similar a una base de datos tabular:
// inventory collection { "name": "Pear", "stock": 20, "nutrition_id": 123, // reference to a nutrition_fact document ... } { "name": "Candy Bar", "stock": 26, "nutrition_id": 456, ... }
// nutrition_facts collection { "_id": 123, "calories": 100, "grams_sugar": 17, "grams_protein": 1, ... } { "_id": 456, "calories": 250, "grams_sugar": 27, "grams_protein": 4, ... }
Si una aplicación solicita la información nutricional de un artículo del inventario antes name del, esta estructura de esquema requiere un de $lookup la nutrition_facts colección para encontrar una entrada que coincida con el del artículo del nutrition_id inventario.
En su lugar, puedes incrustar la información nutricional dentro de la colección inventory:
// inventory collection { "name": "Pear", "stock": 20, "nutrition_facts": { "calories": 100, "grams_sugar": 17, "grams_protein": 1, ... } ... } { "name": "Candy Bar", "stock": 26, "nutrition_facts": { "calories": 250, "grams_sugar": 27, "grams_protein": 4, ... } ... }
De esta manera, al consultar un artículo en inventory, la información nutricional se incluye en el resultado sin necesidad de otra consulta ni una operación $lookup. Considere la posibilidad de incrustar documentos cuando los datos de las colecciones tengan una relación biunívoca.
Uso de arreglos
Considere el siguiente ejemplo donde los documentos de la colección players de una liga de béisbol hacen referencia a documentos de una colección teams, similar a una base de datos tabular:
// players collection { "team_id": 1, // reference to a team document "name": "Nick", "position": "Pitcher" ... } { "team_id": 1, "name": "Anuj", "position": "Shortstop" ... }
// teams collection { "_id": 1, "name": "Danbury Dolphins" ... }
Si una aplicación solicita una lista de jugadores de un equipo, esta estructura de esquema requiere un de $lookup la players colección para encontrar cada jugador que coincida con team_id un.
En su lugar, puedes incluir el players en una matriz en el propio documento del equipo:
// teams collection { "_id": 1, "name": "Danbury Dolphins", "players": [ { "name": "Nick", "position": "Pitcher" ... }, { "name": "Anuj", "position": "Shortstop" ... } ] }
Al usar matrices para almacenar datos relacionados, una aplicación puede recuperar información team completa, incluyendo los jugadores de ese equipo, sin operaciones $lookup ni índices en otras colecciones. En este caso, usar matrices ofrece mayor rendimiento que almacenar la información en colecciones separadas.
Nota
En el ejemplo anterior, los equipos de béisbol tienen un número determinado de jugadores y no existe riesgo de que las formaciones se vuelvan excesivamente grandes.
Consideraciones sobre matrices
El coste de rendimiento de leer y escribir en matrices grandes puede superar el beneficio obtenido al evitar las $lookup operaciones. Si sus matrices son ilimitadas o excesivamente grandes, estas pueden reducir el rendimiento de lectura y escritura.
Si crea un índice en una matriz, cada elemento de la matriz se indexa. Si escribe en esa matriz con frecuencia, el coste de rendimiento de indexar o reindexar un campo de matriz potencialmente grande puede ser significativo.
Desnormalización
La desnormalización de un esquema consiste en duplicar campos o derivar nuevos campos a partir de los existentes. La desnormalización puede mejorar el rendimiento de lectura en diversos casos, como:
Una consulta recurrente requiere algunos campos de un documento grande de otra colección. Puede optar por mantener una copia de esos campos en un documento incrustado en la colección a la que se dirige la consulta recurrente para evitar la fusión de dos colecciones distintas o la realización frecuente de operaciones
$lookup.Con frecuencia se solicita el valor promedio de algún campo de una colección. Puede crear un campo derivado en una colección independiente que se actualice durante sus operaciones de escritura y mantenga un promedio móvil para ese campo.
Si bien se prefiere incrustar documentos o matrices sin duplicación para agrupar datos relacionados, la desnormalización puede mejorar el rendimiento de lectura cuando se deben mantener colecciones separadas.
Nota
Al desnormalizar su esquema, pasa a ser su responsabilidad mantener datos duplicados consistentes.
Obtén más información
La mejor estructura para su esquema depende del contexto de su aplicación. Los siguientes recursos proporcionan información detallada sobre el modelado de datos y ejemplos adicionales de casos de uso para documentos y matrices incrustados:
Modelos de datos
Para obtener más información sobre el modelado de datos en MongoDB y el modelo de esquema flexible, consulte Introducción al modelado de datos.
Para obtener más información sobre las ventajas y desventajas entre los modelos de datos integrados y normalizados, consulte Diseño de modelos de datos.
MongoDB también ofrece un curso universitario gratuito de MongoDB sobre modelado de datos: Modelado de datos para MongoDB.
Presentaciones de modelado de datos de MongoDB.live 2020
Para aprender a incorporar el modelo de datos flexible en su esquema, consulte las siguientes presentaciones de MongoDB.live 2020:
Se puede aprender sobre las relaciones de entidades en MongoDB y ejemplos de sus implementaciones con Modelado de datos con MongoDB.
Se puede aprender sobre patrones avanzados de diseño de esquemas que se pueden incorporar en el esquema establecido con Patrones avanzados de diseño de esquemas.
Arreglos
Para obtener más información sobre cómo consultar matrices en MongoDB, consulte Consultar una matriz.
Patrones de diseño
Para obtener información sobre situaciones en las que los arreglos funcionan bien, consulte los siguientes patrones de diseño:
El uso de El Patrón de Atributos sirve para manejar datos con combinaciones únicas de atributos, como los datos de películas en los que cada película se estrena en un subconjunto de países.
El uso de El patrón Bucket sirve para manejar datos estrechamente agrupados o secuenciales, como los datos de intervalos de tiempo.
Utilice El Patrón Polimórfico para manejar documentos de diferentes formas en la misma colección, como los registros de atletas en varios deportes.
Esquemas desnormalizados
Para leer sobre una situación en la que la duplicación de datos mejora su esquema, consulte el siguiente patrón de diseño:
Se puede utilizar El patrón de referencia extendida para duplicar una porción de datos que se leen con frecuencia de documentos grandes a documentos más pequeños.