Ada beberapa cara untuk mendekati ini tergantung pada format output mana yang paling sesuai dengan kebutuhan Anda. Catatan utama adalah bahwa dengan "kerangka kerja agregasi" itu sendiri, Anda tidak dapat benar-benar mengembalikan sesuatu yang "dilempar" sebagai tanggal, tetapi Anda bisa mendapatkan nilai yang dengan mudah direkonstruksi menjadi Date
objek saat memproses hasil di API Anda.
Pendekatan pertama adalah menggunakan "Operator Agregasi Tanggal" tersedia untuk kerangka kerja agregasi:
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"year": { "$year": "$time" },
"dayOfYear": { "$dayOfYear": "$time" },
"hour": { "$hour": "$time" },
"minute": {
"$subtract": [
{ "$minute": "$time" },
{ "$mod": [ { "$minute": "$time" }, 10 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Yang mengembalikan kunci komposit untuk _id
berisi semua nilai yang Anda inginkan untuk "tanggal". Bergantian jika hanya dalam "jam" selalu maka gunakan saja bagian "menit" dan tentukan tanggal sebenarnya berdasarkan startDate
dari pilihan jangkauan Anda.
Atau Anda bisa menggunakan "Matematika tanggal" biasa untuk mendapatkan milidetik sejak "Epoch" yang lagi-lagi dapat diumpankan ke konstruktor tanggal secara langsung.
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$time", new Date(0) ] },
{ "$mod": [
{ "$subtract": [ "$time", new Date(0) ] },
1000 * 60 * 10
]}
]
},
"count": { "$sum": 1 }
}}
])
Dalam semua kasus apa yang Anda tidak ingin lakukan adalah menggunakan $project
sebelum benar-benar menerapkan $group
. Sebagai "tahap pipa", $project
harus "berputar" melalui semua dokumen yang dipilih dan "mengubah" kontennya.
Ini membutuhkan waktu , dan menambahkan total eksekusi kueri. Anda cukup mendaftar ke $group
langsung seperti yang telah ditunjukkan.
Atau jika Anda benar-benar "murni" tentang Date
objek dikembalikan tanpa pemrosesan pos, maka Anda selalu dapat menggunakan "mapReduce" , karena fungsi JavaScript sebenarnya memungkinkan pembuatan ulang sebagai tanggal, tetapi lebih lambat dari kerangka kerja agregasi dan tentu saja tanpa respons kursor:
db.collection.mapReduce(
function() {
var date = new Date(
this.time.valueOf()
- ( this.time.valueOf() % ( 1000 * 60 * 10 ) )
);
emit(date,1);
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)
Taruhan terbaik Anda adalah menggunakan agregasi, karena mengubah responsnya cukup mudah:
db.collection.aggregate([
{ "$match": {
"time": { "$gte": startDate, "$lt": endDate }
}},
{ "$group": {
"_id": {
"year": { "$year": "$time" },
"dayOfYear": { "$dayOfYear": "$time" },
"hour": { "$hour": "$time" },
"minute": {
"$subtract": [
{ "$minute": "$time" },
{ "$mod": [ { "$minute": "$time" }, 10 ] }
]
}
},
"count": { "$sum": 1 }
}}
]).forEach(function(doc) {
doc._id = new Date(doc._id);
printjson(doc);
})
Dan kemudian Anda memiliki keluaran pengelompokan interval dengan Date
yang sebenarnya objek.