Nieco bardziej nowoczesny niż pierwotna odpowiedź:
db.collection.aggregate([
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": {
"$subtract": ["$date",{"$mod": ["$date",86400000]}]
},
"doc": { "$last": "$$ROOT" }
}},
{ "$replaceRoot": { "newDocument": "$doc" } }
])
Ta sama zasada dotyczy zasadniczo $sort
kolekcja, a następnie $group
na wymaganym kluczu grupowania pobierając $last
dane z granicy grupowania.
Uczynienie rzeczy nieco jaśniejszymi, ponieważ oryginalne pismo jest takie, że możesz użyć $$ROOT
zamiast określania każdej właściwości dokumentu i oczywiście $replaceRoot
etap umożliwia pełne przywrócenie tych danych w postaci oryginalnego dokumentu.
Ale ogólne rozwiązanie to nadal $sort
najpierw $group
we wspólnym kluczu, który jest wymagany i zachowaj $last
lub $first
w zależności od kolejności sortowania wystąpień z granicy grupowania dla wymaganych właściwości.
Również w przypadku dat BSON, w przeciwieństwie do wartości znacznika czasu, jak w pytaniu, zobacz Grupuj wyniki według 15-minutowego przedziału czasu w MongoDb dla różnych podejść do tego, jak akumulować dla różnych przedziałów czasu, faktycznie używając i zwracając wartości daty BSON.
Nie jestem do końca pewien, do czego zmierzasz, ale możesz to zrobić łącznie, jeśli moje zrozumienie jest właściwe. Aby uzyskać ostatni rekord każdego dnia:
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" },
}}
])
Więc zasada jest taka, że biorąc pod uwagę wartość znacznika czasu, wykonaj matematykę z datą, aby wyświetlić ją jako godzinę północy na początku każdego dnia. Następnie jako _id
klawisz na dokumencie jest już monotoniczny (zawsze rosnący), a następnie po prostu zgrupuj na cały dzień
wartość podczas wyciągania $last
dokument od granicy grupowania.
Jeśli nie potrzebujesz wszystkich pól, projektuj i grupuj tylko te, które chcesz.
I tak, możesz to zrobić w ramach Spring Data Framework. Jestem pewien, że jest tam opakowane polecenie. Ale w przeciwnym razie zaklęcie, aby dostać się do natywnego polecenia, wygląda mniej więcej tak:
mongoOps.getCollection("yourCollection").aggregate( ... )
Dla przypomnienia, jeśli faktycznie masz typy dat BSON, a nie znacznik czasu jako liczbę, możesz pominąć matematykę daty:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
},
"hchp": { "$last": "$hchp" }
}}
])