Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
/ / /

Agrupar datos con el patrón de cubo

El patrón de cubos separa las series de datos largas en objetos distintos. Separar grandes conjuntos de datos en grupos más pequeños puede mejorar los patrones de acceso a query y simplificar la lógica de la aplicación. El bucketing es útil cuando tienes objetos similares que se relacionan con una entidad central, como las operaciones con acciones realizadas por un único usuario.

Puedes utilizar el patrón de bucket para la paginación agrupando tus datos según los elementos que tu aplicación muestra por página. Este enfoque utiliza el modelo de datos flexible de MongoDB para almacenar datos según las necesidades de datos de tus aplicaciones.

Tip

Las colecciones de series de tiempo aplican automáticamente el patrón de agrupación y son adecuadas para la mayoría de las aplicaciones que implican la agrupación de datos de series de tiempo.

Considere el siguiente esquema que rastrea las operaciones de acciones. El esquema inicial no utiliza el patrón bucket 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 cubeta para agrupar las operaciones por customerId en grupos de 10.

1

Reorganiza el esquema para que haya 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 de cubo:

  • Los documentos con valores comunes de customerId se condensan en un único documento, con el customerId como un campo de nivel superior.

  • Las transacciones para ese cliente se agrupan en un campo de arreglo incrustado, llamado history.

2
1db.trades.drop()
2
3db.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 valor del campo _id es una concatenación del customerId y la primera hora de negociación en segundos (desde la época unix) en el campo history.

El campo count indica cuántos elementos hay en el arreglo history de ese documento. El campo count se utiliza para implementar la lógica de paginación.

Después de actualizar tu esquema para utilizar el patrón de bucket, actualiza la lógica de tu aplicación para la lectura y escritura de datos. Consulta las siguientes secciones:

  • Query para datos con el patrón Bucket

  • Inserte datos con el patrón Bucket

En el esquema actualizado, cada documento contiene los datos de una sola página de la aplicación. Puede usar el campo _id y count para determinar cómo devolver y actualizar 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 query 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 de skip una unidad menor a la página para la que desea mostrar los datos. Por ejemplo, para mostrar datos de la página 10, ejecute la siguiente query:

db.trades.find( { "_id": /^123_/ } ).sort( { _id: 1 } ).skip(9).limit(1)

Nota

La query anterior no devuelve resultados porque los datos de muestra sólo contienen documentos de la primera página.

Ahora que el esquema utiliza el bucket pattern (patrón de cubo), actualiza la lógica de tu aplicación para insertar nuevas transacciones en el bucket correcto. Utiliza un comando de actualización para insertar la operación en el segmento correspondiente con el customerId y segmento 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 operaciones por página. El filtro de actualización busca un documento para customerId: 123 donde el count sea menor que 10, lo que significa que ese bucket no contiene una página completa de datos.

  • Si hay un documento que coincide con "_id": /^123_/ y su count es menor que 10, el comando update inserta la nueva operación en el arreglo history del documento coincidente.

  • Si no hay un documento que coincida, el comando de actualización inserta un nuevo documento con la nueva operación (porque upsert es true). El campo _id del nuevo documento es una concatenación de customerId y 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 contiene 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")
}
]
}
]

Después de implementar el patrón bucket, no necesitas incorporar lógica de paginación para devolver resultados en tu aplicación. La forma en que se almacenan los datos coincide con la forma en que se utilizan en la aplicación.

Volver

Datos de grupo

Obtén una insignia de habilidad

¡Domina gratis la “Optimización del diseño de esquemas”!

Más información

En esta página