En la colección, tengo entradas como tales:
[ { _id: new ObjectId('61cae11f8fc0b2e3b045be04'), location: 'Station One', datetime: ISODate('2019-02-02T12:54:57.937Z'), sensorType: 'temperature', value: -1.8, __v: 0, }, { _id: new ObjectId('61cae11f8fc0b2e3b045be05'), location: 'Station two', datetime: ISODate('2019-02-02T09:49:39.200Z'), sensorType: 'temperature', value: -2, __v: 0, }, ];
Tengo una consulta agregada para obtener valores mínimos/máximos de cada tipo de sensor así
const queryMinMax = FarmDataModel.aggregate([ { $match: match, }, { $sort: { value: 1, }, }, { $group: { _id: { sensorType: '$sensorType', location: '$location', }, min: { $first: '$$ROOT', }, max: { $last: '$$ROOT', }, }, }, { $sort: { '_id.location': 1, '_id.sensorType': 1, }, }, { $project: { _id: 1, max: { value: '$max.value', month: { $month: '$max.datetime' }, year: { $year: '$max.datetime' }, day: { $dayOfMonth: '$max.datetime' }, }, min: { value: '$min.value', month: { $month: '$min.datetime' }, year: { $year: '$min.datetime' }, day: { $dayOfMonth: '$min.datetime' }, }, }, }, ]);
Esto me da una fila para cada tipo de sensor y los valores mínimos y máximos correspondientes. Lo que me gustaría hacer es agrupar cada tipo de sensor en una ubicación, de modo que la consulta devuelva algo así:
{ 'Station One': { temperature: { min: { value: number; date: date } max: { value: number; date: date }, }, pH: { min: { value: number; date: date } max: { value: number; date: date }, }, }, 'Station Two': { temperature: { min: { value: number; date: date } max: { value: number; date: date }, }, pH: { min: { value: number; date: date } max: { value: number; date: date }, }, }, };
Entonces, si antes obtenía 4 filas, una para cada tipo de sensor en cada ubicación, ahora obtendría dos filas, una para cada ubicación y debajo de ellas hay pares clave:valor para cada tipo de sensor
¿Cómo puedo modificar mi consulta para lograr eso?
Simplemente puede construir sobre su tubería existente, todo lo que necesita es otra etapa de $group
para agrupar los datos por estación, luego reestructurarlos para que coincidan con el resultado que desea, así:
db.collection.aggregate([ ... existing pipeline, { $group: { _id: "$_id.location", sensorData: { $push: { k: "$_id.sensorType", v: { max: "$max", min: "$min" } } } } }, { "$replaceRoot": { "newRoot": { "$arrayToObject": [ [ { k: "$_id", v: { "$arrayToObject": "$sensorData" } } ] ] } } } ])