Almacenar arreglos como valores de campo te permite integrar datos y asegurarte de que los datos que se acceden juntos se almacenen juntos. Sin embargo, si no se limita el número de elementos en un arreglo, los documentos pueden exceder el Límite de tamaño del documento BSON de16MB. Un arreglo sin límites puede agotar los recursos de una aplicación y disminuir el rendimiento del índice.
En lugar de incrustar conjuntos de datos completos, utiliza subconjuntos y referencias a arreglos limitados, lo que puede mejorar el rendimiento y mantener dentro de límites el tamaño de los documentos. Al seleccionar subconjuntos de datos, sólo se eligen las partes necesarias de los datos posteriores con los que se van a trabajar, lo que reduce el uso de memoria y el tiempo de procesamiento al centrarse solo en los datos relevantes. Cuando haces referencia a datos, conectas con fuentes de datos externas en lugar de incrustarlas directamente en tus documentos. Este enfoque mejora el rendimiento y reduce el tamaño del documento. Al utilizar subsetting y referencia, puedes limitar arreglos y administrar tus fechas de manera más eficiente.
Ejemplo
Considere el siguiente esquema que rastrea reseñas de libros para una aplicación de librería. El esquema inicial utiliza una matriz para reviews .
{ title: "Harry Potter", author: "J.K. Rowling", publisher: "Scholastic", reviews: [ { user: "Alice", review: "Great book!", rating: 5 }, { user: "Bob", review: "Didn't like it!", rating: 1 }, { user: "Charlie", review: "Not bad, but could be better.", rating: 3 } ] }
En este esquema, el campo reviews es una matriz ilimitada. Cada vez que se crea una nueva reseña para este libro, la aplicación añade un nuevo subdocumento a la matriz reviews. A medida que se añaden más reseñas, la matriz puede crecer demasiado y sobrecargar los recursos de la aplicación.
En este ejemplo, la aplicación de librería solo necesita mostrar tres reseñas por libro. Para evitar matrices ilimitadas, puede usar el patrón de diseño de subconjuntos o referencias de documentos, según su caso de uso.
Patrón de subconjunto
La creación de subconjuntos de datos es ideal cuando se necesita acceder rápidamente a datos que no se actualizan con frecuencia. Con el patrón de subconjunto, se pueden incrustar tres de las revisiones en el documento del libro para obtener toda la información necesaria en una sola operación. Las demás revisiones se almacenan en una colección reviews independiente. Este patrón de diseño de esquema ofrece las siguientes ventajas:
Se elimina el arreglo no limitado
Controlar el tamaño del documento
Evite el uso de múltiples queries
La colección books:
db.books.insertOne( [ { title: "Harry Potter", author: "J.K. Rowling", publisher: "Scholastic", reviews: [ { reviewer: "Alice", review: "Great book!", rating: 5 }, { reviewer: "Charlie", review: "Didn't like it.", rating: 1 }, { reviewer: "Bob", review: "Not bad, but could be better.", rating: 3 } ], } ] )
La colección reviews:
db.reviews.insertMany( [ { reviewer: "Jason", review: "Did not enjoy!", rating: 1 }, { reviewer: "Pam", review: "Favorite book!", rating: 5 }, { reviewer: "Bob", review: "Not bad, but could be better.", rating: 3 } ] )
Este enfoque duplica datos, lo que hace que las actualizaciones sean costosas. Este enfoque es el mejor si las revisiones no se actualizan con frecuencia.
Datos de referencia
La referencia de datos es la mejor opción cuando necesita administrar conjuntos de datos grandes o actualizados con frecuencia sin aumentar el tamaño de los documentos.
Para referenciar datos, guarde las reseñas en una colección aparte y añada un campo review_id a los documentos de la colección reviews. Utilice el campo review_id para referenciar las reseñas de la colección books.
Este enfoque resuelve el problema del arreglo ilimitado, pero introduce latencia porque necesitas consultar la colección reviews para obtener información de reseñas para la colección books. Dependiendo del caso de uso, esta latencia adicional puede ser un intercambio aceptable para evitar los problemas causados por arreglos ilimitados.
La colección books:
db.books.insertMany( [ { title: "Harry Potter", author: "J.K. Rowling", publisher: "Scholastic", reviews: ["review1", "review2", "review3"] }, { title: "Pride and Prejudice", author: "Jane Austen", publisher: "Penguin", reviews: ["review4", "review5"] } ] )
La colección reviews:
db.reviews.insertMany( [ { review_id: "review1", reviewer: "Jason", review: "Did not enjoy!", rating: 1 }, { review_id: "review2", reviewer: "Pam", review: "Favorite book!", rating: 5 }, { review_id: "review3", reviewer: "Bob", review: "Not bad, but could be better.", rating: 3 }, { review_id: "review4", reviewer: "Tina", review: "Amazing!", rating: 5 }, { review_id: "review5", reviewer: "Jacob", review: "A little overrated", rating: 4, } ] )
Usa $lookup para unirte a un campo de arreglo
Si tu información de books y reviews está almacenada en colecciones separadas, la aplicación necesita realizar una operación de $lookup para unir los datos.
La siguiente operación de agregación une las colecciones books y reviews del ejemplo anterior.
db.books.aggregate( [ { $lookup: { from: "reviews", localField: "reviews", foreignField: "review_id", as: "reviewDetails" } } ] )
La operación devuelve lo siguiente:
[ { _id: ObjectId('665de81eeda086b5e22dbcc9'), title: 'Harry Potter', author: 'J.K. Rowling', publisher: 'Scholastic', reviews: [ 'review1', 'review2', 'review3' ], reviewDetails: [ { _id: ObjectId('665de82beda086b5e22dbccb'), review_id: 'review1', reviewer: 'Jason', review: 'Did not enjoy!', rating: 1 }, { _id: ObjectId('665de82beda086b5e22dbccc'), review_id: 'review2', reviewer: 'Pam', review: 'Favorite book!', rating: 5 }, { _id: ObjectId('665de82beda086b5e22dbccd'), review_id: 'review3', reviewer: 'Bob', review: 'Not bad, but could be better.', rating: 3 } ] }, { _id: ObjectId('665de81eeda086b5e22dbcca'), title: 'Pride and Prejudice', author: 'Jane Austen', publisher: 'Penguin', reviews: [ 'review4', 'review5' ], reviewDetails: [ { _id: ObjectId('665de82beda086b5e22dbcce'), review_id: 'review4', reviewer: 'Tina', review: 'Amazing!', rating: 5 }, { _id: ObjectId('665de82beda086b5e22dbccf'), review_id: 'review5', reviewer: 'Jacob', review: 'A little overrated', rating: 4 } ] } ]
En este ejemplo, la operación $lookup une la colección books con la colección reviews utilizando el arreglo reviews en el documento del libro y el campo review_id en los documentos de reseñas. El documento reviewDetails almacena los datos combinados.