Малко по-модерен от оригиналния отговор:
db.collection.aggregate([
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": {
"$subtract": ["$date",{"$mod": ["$date",86400000]}]
},
"doc": { "$last": "$$ROOT" }
}},
{ "$replaceRoot": { "newDocument": "$doc" } }
])
Прилага се същият принцип, че по същество $sort
колекцията и след това $group
върху необходимия ключ за групиране, като вземете $last
данни от границата на групиране.
Правейки нещата малко по-ясни след оригиналното писане е, че можете да използвате $$ROOT
вместо да посочвате всяко свойство на документа и, разбира се, $replaceRoot
етап ви позволява да възстановите тези данни напълно като оригиналната форма на документ.
Но общото решение все още е $sort
първо, след това $group
върху общия ключ, който се изисква, и запазете $lastкод>
или $first
в зависимост от възникването на реда на сортиране от границата на групиране за необходимите свойства.
Също така за BSON дати, за разлика от стойността на клеймото за време, както е във въпроса, вижте Групиран резултат по 15 минути интервал от време в MongoDb за различни подходи за това как да се натрупват за различни интервали от време, като действително се използват и връщат BSON стойности за дата.
Не съм съвсем сигурен какво търсите тук, но бихте могли да направите това обобщено, ако разбирам правилно. И така, за да получите последния запис за всеки ден:
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" },
}}
])
Така че принципът тук е, че като се има предвид стойността на клеймото за време, направете математиката на датата, за да проектирате това като полунощ в началото на всеки ден. След това като _id
ключ на документа вече е монотонен (винаги се увеличава), тогава просто групирайте на wholeDay
стойност, докато изтегляте $last
документ от границата на групиране.
Ако нямате нужда от всички полета, тогава проектирайте и групирайте само тези, които искате.
И да, можете да направите това в пролетната рамка на данни. Сигурен съм, че там има опакована команда. Но в противен случай заклинанието за достигане до основната команда е нещо подобно:
mongoOps.getCollection("yourCollection").aggregate( ... )
За протокола, ако действително сте имали BSON типове дати, а не клеймо за време като число, можете да пропуснете изчислението на датата:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
},
"hchp": { "$last": "$hchp" }
}}
])