Tengo una colección en la que almaceno agua dispensada para un día en particular. Ahora, durante algunos días, cuando el dispositivo no funciona, los datos no se almacenan en la base de datos y no obtendré los datos en la colección. Por ejemplo, estoy consultando el agua dispensada durante los últimos 7 días donde el dispositivo solo funcionó durante dos días y me da algo como esto:
[{ "uID" : "12345678", "midNightTimeStamp" : NumberInt(1645381800), "waterDispensed" : NumberInt(53) }, { "uID" : "12345678", "midNightTimeStamp" : NumberInt(1645641000), "waterDispensed" : NumberInt(30) }]La conversión de las dos marcas de tiempo anteriores me da datos para el lunes 21 de febrero y el jueves 24 de febrero. Ahora, si ejecuto la consulta del 21 de febrero al 27 de febrero, algo como esto,
db.getCollection("analytics").find({ uID: "12345678", midNightTimeStamp: {"$in": [1645381800, 1645468200, 1645554600, 1645641000, 1645727400, 1645813800, 1645900200]}})Esto me devuelve solo dos documentos anteriores, cómo completar los valores faltantes para midNightTimeStamp proporcionados para obtener la lista de documentos como esta que no existe:
[{ "uID" : "12345678", "midNightTimeStamp" : 1645381800, "waterDispensed" : 53 }, { "uID" : "12345678", "midNightTimeStamp" : 1645468200, "waterDispensed" : 0 }, { "uID" : "12345678", "midNightTimeStamp" : 1645554600, "waterDispensed" : 0 }, { "uID" : "12345678", "midNightTimeStamp" : 1645641000, "waterDispensed" : 30 }, { "uID" : "12345678", "midNightTimeStamp" : 1645727400, "waterDispensed" : 0 }, { "uID" : "12345678", "midNightTimeStamp" : 1645813800, "waterDispensed" : 0 }, { "uID" : "12345678", "midNightTimeStamp" : 1645900200, "waterDispensed" : 0 }Tal vez algo como esto:
db.collection.aggregate([ { $group: { _id: null, ar: { $push: "$$ROOT" }, mind: { "$min": "$midNightTimeStamp" }, maxd: { "$max": "$midNightTimeStamp" } } }, { $project: { ar: { $map: { input: { $range: [ "$mind", { "$sum": [ "$maxd", 86400 ] }, 86400 ] }, as: "dateInRange", in: { $let: { vars: { dateIndex: { "$indexOfArray": [ "$ar.midNightTimeStamp", "$$dateInRange" ] } }, in: { $cond: { if: { $ne: [ "$$dateIndex", -1 ] }, then: { $arrayElemAt: [ "$ar", "$$dateIndex" ] }, else: { midNightTimeStamp: "$$dateInRange", "waterDispensed": NumberInt(0) } } } } } } } } }, { $unwind: "$ar" }, { $project: { _id: 0, "waterDispensed": "$ar.waterDispensed", midNightTimeStamp: "$ar.midNightTimeStamp", "Date": { $toDate: { "$multiply": [ "$ar.midNightTimeStamp", 1000 ] } } } } ])Explicado:
Esto es un poco diferente a la otra respuesta, y se encarga de tomar el "uID" deseado. Los comentarios en el MQL explican el proceso.
db.collection.aggregate([ { // The uID we want "$match": { "uID": "12345678" } }, { // grab all the uID docs as "water" // keep uID "$group": { "_id": null, "water": { "$push": "$$CURRENT" }, "uID": { "$first": "$uID" } } }, { // create outArray "$set": { "outArray": { // by mapping time vals "$map": { "input": { "$range": [ NumberInt(1645381800), NumberInt(1645900200), 86400 ] }, "in": { "$cond": [ { // already have doc? "$in": [ "$$this", "$water.midNightTimeStamp" ] }, { // yes! Get it! "$arrayElemAt": [ "$water", { "$indexOfArray": [ "$water.midNightTimeStamp", "$$this" ] } ] }, { // no, create it "uID": "$uID", "midNightTimeStamp": "$$this", "waterDispensed": 0 } ] } } } } }, { // only need outArray now "$project": { "_id": 0, "outArray": 1 } }, { // create docs "$unwind": "$outArray" }, { // hoist them "$replaceWith": "$outArray" }, { // don't need _id "$unset": "_id" } ])Pruébalo en mongoplayground.net .