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 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 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 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 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 del 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 de ese cliente se agrupan en un campo de matriz 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 la matriz 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

  • Insertar 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 de actualización inserta la nueva transacción en la matriz 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