Sedikit lebih modern daripada jawaban aslinya:
db.collection.aggregate([
{ "$sort": { "date": 1 } },
{ "$group": {
"_id": {
"$subtract": ["$date",{"$mod": ["$date",86400000]}]
},
"doc": { "$last": "$$ROOT" }
}},
{ "$replaceRoot": { "newDocument": "$doc" } }
])
Prinsip yang sama berlaku bahwa Anda pada dasarnya $sort
koleksi dan kemudian $group
pada kunci pengelompokan yang diperlukan mengambil $last
data dari batas pengelompokan.
Membuat segalanya sedikit lebih jelas karena tulisan aslinya adalah Anda dapat menggunakan $$ROOT
alih-alih menentukan setiap properti dokumen, dan tentu saja $replaceRoot
stage memungkinkan Anda untuk memulihkan data tersebut sepenuhnya sebagai bentuk dokumen asli.
Tetapi solusi umumnya masih $sort
pertama, lalu $group
pada kunci umum yang diperlukan dan simpan $last
atau $first
tergantung pada kemunculan urutan pengurutan dari batas pengelompokan untuk properti yang diperlukan.
Juga untuk Tanggal BSON yang bertentangan dengan nilai stempel waktu seperti dalam pertanyaan, lihat Kelompokkan hasil berdasarkan interval waktu 15 menit di MongoDb untuk pendekatan berbeda tentang cara mengakumulasi untuk interval waktu berbeda yang sebenarnya menggunakan dan mengembalikan nilai Tanggal BSON.
Tidak yakin apa yang Anda tuju di sini tetapi Anda bisa melakukan ini secara agregat jika pemahaman saya benar. Jadi untuk mendapatkan rekor terakhir setiap hari:
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" },
}}
])
Jadi prinsipnya di sini adalah bahwa mengingat nilai stempel waktu, lakukan matematika tanggal untuk memproyeksikannya sebagai waktu tengah malam di awal setiap hari. Kemudian sebagai _id
key pada dokumen sudah monoton (selalu meningkat), maka cukup group pada wholeDay
nilai sambil menarik $last
dokumen dari batas pengelompokan.
Jika Anda tidak membutuhkan semua bidang, cukup proyeksikan dan kelompokkan bidang yang Anda inginkan.
Dan ya, Anda dapat melakukan ini dalam kerangka data pegas. Saya yakin ada perintah yang dibungkus di sana. Tetapi sebaliknya, mantra untuk mendapatkan perintah asli berbunyi seperti ini:
mongoOps.getCollection("yourCollection").aggregate( ... )
Sebagai catatan, jika Anda benar-benar memiliki tipe tanggal BSON daripada stempel waktu sebagai angka, maka Anda dapat melewati matematika tanggal:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"day": { "$dayOfMonth": "$date" }
},
"hchp": { "$last": "$hchp" }
}}
])