Ada beberapa cara untuk melakukannya.
Yang pertama adalah dengan Operator Agregasi Tanggal, yang memungkinkan Anda untuk membedah nilai "tanggal" dalam dokumen. Khusus untuk "pengelompokan" sebagai maksud utama:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"dayOfYear": { "$dayOfYear": "$created_at" },
"hour": { "$hour": "$created_at" },
"interval": {
"$subtract": [
{ "$minute": "$created_at" },
{ "$mod": [{ "$minute": "$created_at"}, 15] }
]
}
}},
"count": { "$sum": 1 }
}}
])
Cara kedua adalah dengan menggunakan sedikit trik ketika objek tanggal dikurangi (atau operasi matematika langsung lainnya) dari objek tanggal lain, maka hasilnya adalah nilai numerik yang mewakili milidetik cap waktu zaman antara dua objek. Jadi hanya dengan menggunakan tanggal Epoch Anda mendapatkan representasi Epoch milidetik. Kemudian gunakan matematika tanggal untuk interval:
db.collection.aggregate([
{ "$group": {
"_id": {
"$subtract": [
{ "$subtract": [ "$created_at", new Date("1970-01-01") ] },
{ "$mod": [
{ "$subtract": [ "$created_at", new Date("1970-01-01") ] },
1000 * 60 * 15
]}
]
},
"count": { "$sum": 1 }
}}
])
Jadi itu tergantung pada jenis format output yang Anda inginkan untuk interval pengelompokan. Keduanya pada dasarnya mewakili hal yang sama dan memiliki data yang cukup untuk dikonstruksi ulang sebagai objek "tanggal" dalam kode Anda.
Anda dapat meletakkan apa pun yang Anda inginkan di bagian "operator pengelompokan" setelah pengelompokan _id
. Saya hanya menggunakan contoh "hitungan" dasar sebagai pengganti pernyataan nyata dari diri Anda tentang apa yang benar-benar ingin Anda lakukan.
MongoDB 4.x dan ke Atas
Ada beberapa tambahan pada Operator Agregasi Tanggal sejak penulisan aslinya, tetapi dari MongoDB 4.0 akan ada "pengecoran tipe nyata" yang sebenarnya sebagai lawan dari trik matematika dasar yang dilakukan di sini dengan konversi Tanggal BSON.
Misalnya kita dapat menggunakan $toLong
dan $toDate
sebagai pembantu baru di sini:
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": "$created_at" },
{ "$mod": [ { "$toLong": "$created_at" }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Itu sedikit lebih pendek dan tidak perlu mendefinisikan Tanggal BSON eksternal untuk nilai "Epoch" sebagai konstanta dalam mendefinisikan pipeline sehingga cukup konsisten untuk semua implementasi bahasa.
Itu hanyalah dua dari metode "pembantu" untuk konversi tipe yang semuanya terkait dengan $convert
metode, yang merupakan bentuk implementasi "lebih panjang" yang memungkinkan penanganan khusus pada null
atau kesalahan dalam konversi.
Bahkan dimungkinkan dengan casting seperti itu untuk mendapatkan Date
informasi dari ObjectId
dari kunci utama, karena ini akan menjadi sumber tanggal "pembuatan" yang dapat diandalkan:
db.collection.aggregate([
{ "$group": {
"_id": {
"$toDate": {
"$subtract": [
{ "$toLong": { "$toDate": "$_id" } },
{ "$mod": [ { "$toLong": { "$toDate": "$_id" } }, 1000 * 60 * 15 ] }
]
}
},
"count": { "$sum": 1 }
}}
])
Jadi "jenis casting" dengan konversi semacam ini bisa menjadi alat yang cukup ampuh.
Peringatan -
ObjectId
nilai terbatas pada presisi hingga detik hanya untuk nilai waktu internal yang merupakan bagian dari data mereka yang memungkinkan$toDate
konversi. "Waktu" yang dimasukkan sebenarnya kemungkinan besar tergantung pada driver yang digunakan. Dimana presisi diperlukan, masih disarankan untuk menggunakan bidang Tanggal BSON diskrit daripada mengandalkanObjectId
nilai.