Um pouco mais moderno que a resposta original:
db.collection.aggregate([
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": {
"$subtract": ["$date",{"$mod": ["$date",86400000]}]
},
"doc": { "$last": "$$ROOT" }
}},
{ "$replaceRoot": { "newDocument": "$doc" } }
])
O mesmo princípio se aplica a você essencialmente
$sort
a coleção e, em seguida, $group
na chave de agrupamento necessária, pegando o $last
dados do limite de agrupamento. Tornando as coisas um pouco mais claras, já que a escrita original é que você pode usar
$$ROOT
em vez de especificar cada propriedade do documento e, claro, o $replaceRoot
stage permite que você restaure esses dados totalmente como o formulário do documento original. Mas a solução geral ainda é
$sort
primeiro, depois $group
na chave comum necessária e mantenha o $last
ou $first
dependendo das ocorrências de ordem de classificação do limite de agrupamento para as propriedades necessárias. Também para datas BSON em vez de um valor de carimbo de data/hora como na pergunta, consulte Resultado do grupo por intervalo de tempo de 15 minutos no MongoDb para diferentes abordagens sobre como acumular para diferentes intervalos de tempo realmente usando e retornando valores de data BSON.
Não tenho certeza do que você está procurando aqui, mas você pode fazer isso de forma agregada, se meu entendimento estiver correto. Então, para obter o último registro para cada dia:
db.collection.aggregate([
// Sort in date order as ascending
{"$sort": { "date": 1 } },
// Date math converts to whole day
{"$project": {
"adco": 1,
"hchc": 1,
"hchp": 1,
"hhphc": 1,
"ptec": 1,
"iinst": 1,
"papp": 1,
"imax": 1,
"optarif": 1,
"isousc": 1,
"motdetat": 1,
"date": 1,
"wholeDay": {"$subtract": ["$date",{"$mod": ["$date",86400000]}]}
}},
// Group on wholeDay ( _id insertion is monotonic )
{"$group":
"_id": "$wholeDay",
"docId": {"$last": "$_id" },
"adco": {"$last": "$adco" },
"hchc": {"$last": "$hchc" },
"hchp": {"$last": "$hchp" },
"hhphc": {"$last": "$hhphc" },
"ptec": {"$last": "$ptec" },
"iinst": {"$last": "$iinst" },
"papp": {"$last": "$papp" },
"imax": {"$last": "$imax" },
"optarif": {"$last": "$optarif",
"isousc": {"$last": "$isouc" },
"motdetat": {"$last": "$motdetat" },
"date": {"$last": "$date" },
}}
])
Portanto, o princípio aqui é que, dado o valor do carimbo de data/hora, faça a matemática da data para projetar isso como a hora da meia-noite no início de cada dia. Então, como
_id
key no documento já é monotônico (sempre crescente), então simplesmente agrupe no wholeDay
valor ao puxar o $last
documento do limite de agrupamento. Se você não precisar de todos os campos, apenas projete e agrupe os que deseja.
E sim, você pode fazer isso na estrutura de dados da primavera. Tenho certeza de que há um comando encapsulado lá. Mas, caso contrário, o encantamento para chegar ao comando nativo é algo assim:
mongoOps.getCollection("yourCollection").aggregate( ... )
Para o registro, se você realmente tinha tipos de data BSON em vez de um carimbo de data/hora como um número, você pode pular a matemática de datas:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
},
"hchp": { "$last": "$hchp" }
}}
])