El patrón de bucket separa largas series de datos en objetos distintos. Separar grandes series de datos en grupos más pequeños puede mejorar los patrones de acceso a las consultas y simplificar la lógica de la aplicación. La segmentación es útil cuando se tienen objetos similares relacionados con una entidad central, como las operaciones bursátiles realizadas por un solo usuario.
Puede usar el patrón de cubo para la paginación, agrupando sus datos según los elementos que su aplicación muestra por página. Este enfoque utiliza el modelo de datos flexible de MongoDB para almacenar datos según las necesidades de sus aplicaciones.
Tip
Las colecciones de series de tiempo aplican el patrón de contenedor automáticamente y son adecuadas para la mayoría de las aplicaciones que implican la agrupación en contenedores de datos de series de tiempo.
Acerca de esta tarea
Considere el siguiente esquema que rastrea las operaciones bursátiles. El esquema inicial no utiliza el patrón de cubo y almacena cada operación en un documento individual.
db.trades.insertMany( [ { "ticker" : "MDB", "customerId": 123, "type" : "buy", "quantity" : 419, "date" : ISODate("2023-10-26T15:47:03.434Z") }, { "ticker" : "MDB", "customerId": 123, "type" : "sell", "quantity" : 29, "date" : ISODate("2023-10-30T09:32:57.765Z") }, { "ticker" : "GOOG", "customerId": 456, "type" : "buy", "quantity" : 50, "date" : ISODate("2023-10-31T11:16:02.120Z") } ] )
La aplicación muestra las operaciones de acciones realizadas por un solo cliente a la vez, y muestra 10 operaciones por página. Para simplificar la lógica de la aplicación, utilice el patrón de cubo para agrupar las operaciones por customerId en grupos de 10.
Pasos
Agrupar los datos por customerId.
Reorganice el esquema para tener un solo documento para cada customerId:
{ "customerId": 123, "history": [ { "type": "buy", "ticker": "MDB", "qty": 419, "date": ISODate("2023-10-26T15:47:03.434Z") }, { "type": "sell", "ticker": "MDB", "qty": 29, "date": ISODate("2023-10-30T09:32:57.765Z") } ] }, { "customerId": 456, "history": [ { "type" : "buy", "ticker" : "GOOG", "quantity" : 50, "date" : ISODate("2023-10-31T11:16:02.120Z") } ] }
Con el patrón del cubo:
Los documentos con valores
customerIdcomunes se condensan en un solo documento, dondecustomerIdes un campo de nivel superior.Las transacciones de ese cliente se agrupan en un campo de matriz incrustado, llamado
history.
Agregue un identificador y un recuento para cada depósito.
1 db.trades.drop() 2 3 db.trades.insertMany( 4 [ 5 { 6 "_id": "123_1698349623", 7 "customerId": 123, 8 "count": 2, 9 "history": [ 10 { 11 "type": "buy", 12 "ticker": "MDB", 13 "qty": 419, 14 "date": ISODate("2023-10-26T15:47:03.434Z") 15 }, 16 { 17 "type": "sell", 18 "ticker": "MDB", 19 "qty": 29, 20 "date": ISODate("2023-10-30T09:32:57.765Z") 21 } 22 ] 23 }, 24 { 25 "_id": "456_1698765362", 26 "customerId": 456, 27 "count": 1, 28 "history": [ 29 { 30 "type" : "buy", 31 "ticker" : "GOOG", 32 "quantity" : 50, 33 "date" : ISODate("2023-10-31T11:16:02.120Z") 34 } 35 ] 36 }, 37 ] 38 )
El _id valor del campo es una concatenación de customerId y el primer tiempo de transacción en segundos (desde la history época de Unix) en el campo.
El campo count indica cuántos elementos hay en la matriz history de ese documento. El campo count se utiliza para implementar la lógica de paginación.
Próximos pasos
Después de actualizar su esquema para usar el patrón de bucket, actualice la lógica de su aplicación para leer y escribir datos. Consulte las siguientes secciones:
Consulta de datos con el patrón Bucket
En el esquema actualizado, cada documento contiene datos de una sola página de la aplicación. Puede usar los campos _id y count para determinar cómo devolver y actualizar los datos.
Para query datos en la página adecuada, usa una consulta regex para devolver datos de un(a) customerId especificado(a), y usa skip para regresar a los datos de la página correcta. La consulta regex en _id utiliza el índice _id por defecto, lo que da como resultado consultas eficientes sin la necesidad de un índice adicional.
La siguiente consulta devuelve datos para la primera página de transacciones del cliente 123:
db.trades.find( { "_id": /^123_/ } ).sort( { _id: 1 } ).limit(1)
Para devolver datos de páginas posteriores, especifique un valor skip menor que el de la página cuyos datos desea mostrar. Por ejemplo, para mostrar los datos de la página 10, ejecute la siguiente consulta:
db.trades.find( { "_id": /^123_/ } ).sort( { _id: 1 } ).skip(9).limit(1)
Nota
La consulta anterior no devuelve ningún resultado porque los datos de muestra solo contienen documentos de la primera página.
Insertar datos con el patrón Bucket
Ahora que el esquema usa el patrón de depósito, actualice la lógica de su aplicación para insertar nuevas operaciones en el depósito correcto. Use un comando de actualización para insertar la operación en el depósito con el customerId y el depósito adecuados.
El siguiente comando inserta una nueva operación para customerId: 123:
db.trades.updateOne( { "_id": /^123_/, "count": { $lt: 10 } }, { "$push": { "history": { "type": "buy", "ticker": "MSFT", "qty": 42, "date": ISODate("2023-11-02T11:43:10") } }, "$inc": { "count": 1 }, "$setOnInsert": { "_id": "123_1698939791", "customerId": 123 } }, { upsert: true } )
La aplicación muestra 10 transacciones por página. El filtro de actualización busca un documento para customerId: 123 donde count sea menor que 10, lo que significa que el contenedor no contiene una página completa de datos.
Si hay un documento que coincide con
"_id": /^123_/y sucountes menor que 10, el comando de actualización inserta la nueva transacción en la matrizhistorydel documento coincidente.Si no hay un documento que coincida, el comando de actualización inserta un nuevo documento con la nueva operación (porque
upsertestrue). El campo_iddel nuevo documento es una concatenación decustomerIdy el tiempo en segundos desde la Unix epoch de la operación.
La lógica para los comandos de actualización evita arreglos sin límites asegurando que ningún arreglo history contenga más de 10 documentos.
Después de ejecutar la operación de actualización, la colección trades tiene los siguientes documentos:
[ { _id: '123_1698349623', customerId: 123, count: 3, history: [ { type: 'buy', ticker: 'MDB', qty: 419, date: ISODate("2023-10-26T15:47:03.434Z") }, { type: 'sell', ticker: 'MDB', qty: 29, date: ISODate("2023-10-30T09:32:57.765Z") }, { type: 'buy', ticker: 'MSFT', qty: 42, date: ISODate("2023-11-02T11:43:10.000Z") } ] }, { _id: '456_1698765362', customerId: 456, count: 1, history: [ { type: 'buy', ticker: 'GOOG', quantity: 50, date: ISODate("2023-10-31T11:16:02.120Z") } ] } ]
Resultados
Tras implementar el patrón de bucket, no es necesario incorporar lógica de paginación para devolver resultados en la aplicación. La forma en que se almacenan los datos coincide con su uso en la aplicación.