Diga los datos de la tienda de colección en el siguiente formato. Cada día se añade una nueva entrada a la colección. Las fechas están en formato ISO.
|id|dt|data| --- |1|2021-03-17|{key:"A", value:"B"} ... |1|2021-03-14|{key:"A", value:"B"} ... |1|2021-02-28|{key:"A", value:"B"} |1|2021-02-27|{key:"A", value:"B"} ... |1|2021-02-01|{key:"A", value:"B"} |1|2021-01-31|{key:"A", value:"B"} |1|2021-01-30|{key:"A", value:"B"} ... |1|2021-01-01|{key:"A", value:"B"} |1|2020-12-31|{key:"A", value:"B"} ... |1|2020-11-30|{key:"A", value:"B"} ...Necesito ayuda con una consulta que me da el ultimo dia de cada mes para un periodo de tiempo determinado. A continuación se muestra la consulta que pude hacer que no da el último día del mes actual, ya que lo estoy ordenando por día, mes y año.
db.getCollection('data').aggregate([ { $match: {dt: {$gt: ISODate("2020-01-01")} }, { $project: { dt: "$dt", month: { $month: "$dt" }, day: { $dayOfMonth: "$dt" }, year: { $year: "$dt" }, data: "$data" } }, { $sort: {day: -1, month: -1, year: -1} }, { $limit: 24}, { $sort: {dt: -1} }, ])Los resultados que busco son:
|1|2021-03-17|{key:"A", value:"B"} |1|2021-02-28|{key:"A", value:"B"} |1|2021-01-31|{key:"A", value:"B"} |1|2020-12-31|{key:"A", value:"B"} |1|2020-11-30|{key:"A", value:"B"} ... |1|2020-01-31|{key:"A", value:"B"}Agrupe los registros por año y mes, obtenga la fecha máxima para ese mes.
db.getCollection('data').aggregate([ { $match: { dt: { $gt: ISODate("2020-01-01") } } }, { $group: { // group by _id: { $substr: ['$dt', 0, 7] }, // get year and month eg 2020-01 dt: { $max: "$dt" }, // find the max date doc:{ "$first" : "$$ROOT" } } // to get the document }, { "$replaceRoot": { "newRoot": "$doc"} }, // project the document { $sort: { dt: -1 } } ]);Mono parcheó una posible solución para usted en Python, pero sin su base de datos, no puedo estar seguro de que esto funcione.
Primero, hay una función que toma un número entero que representa un mes y devuelve el último día de ese mes.
import datetime as dt def last_day_of_month(month): return dt.datetime(2021, month+1, 1) - dt.timedelta(days=1)Luego, construí la consulta con una función separada.
def build_query(last_month): return [ { "$and": [ {"date": {"$gte": last_day_of_month(i)}}, {"date": {"$lt": last_day_of_month(i) + dt.timedelta(days=1)}} ] } for i in range(0, last_month) ] Aquí está la salida. Estaría dentro de un operador $or en la etapa $match .
{'$match': {'$or': [{'$and': [{'date': {'$gte': datetime.datetime(2020, 12, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 1, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 1, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 2, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 2, 28, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 3, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 3, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 4, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 4, 30, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 5, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 5, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 6, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 6, 30, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 7, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 7, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 8, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 8, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 9, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 9, 30, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 10, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 10, 31, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 11, 1, 0, 0)}}]}, {'$and': [{'date': {'$gte': datetime.datetime(2021, 11, 30, 0, 0)}}, {'date': {'$lt': datetime.datetime(2021, 12, 1, 0, 0)}}]}]}}