Almacenar matrices como valores de campo permite incrustar datos y garantizar que los datos a los que se accede conjuntamente se almacenen juntos. Sin embargo, si no se limita el número de elementos de una matriz, los documentos podrían superar el límite. 16Límite de tamaño de documento BSON de MB. Una matriz ilimitada puede sobrecargar los recursos de la aplicación y reducir 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 campo.
{ 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:
Eliminar la matriz ilimitada
Controlar el tamaño del documento
Evite el uso de múltiples consultas
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 los datos, lo que encarece las actualizaciones. Es recomendable 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 de la matriz ilimitada, pero introduce latencia, ya que es necesario consultar la colección reviews para recuperar la información de revisión de la colección books. Dependiendo del caso de uso, esta latencia adicional puede ser una compensación aceptable para evitar los problemas causados por las matrices ilimitadas.
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, } ] )
Utilice $lookup para unirse a un campo de matriz
Si la books reviews información y se almacena en colecciones separadas, la aplicación debe realizar una $lookup operación para unir los datos.
La siguiente operación de agregación une la colección 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 mediante la matriz reviews del documento del libro y el campo review_id de los documentos de reseñas. El documento reviewDetails almacena los datos combinados.