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 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.

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.

1

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 customerId comunes se condensan en un solo documento, donde customerId es 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 _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.

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

  • Insertar 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.

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 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 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")
}
]
}
]

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.

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