Anda telah menulis semua tahapan, Tapi masalahnya di sini adalah tidak ada hubungan antara satu sama lain, Berarti perubahan yang dilakukan pada pengaturan sebelumnya tidak tercermin pada langkah selanjutnya. Beberapa masalah :
{$sort: {$dateFromString:{time: 1}}} // You can't use `$dateFromString` in sort stage. Also syntax of `$dateFromString` is incorrect.
Misalkan jika itu berhasil (tidak akan tetapi menganggap ) Anda tidak benar-benar mengonversi time
&menyimpan waktu yang dikonversi ke variabel untuk digunakan nanti di $group
atau lebih jauh ke bawah tahap. Jadi, Anda perlu menyimpannya ke variabel di dokumen masing-masing menggunakan $addFields
atau $project
. Saya belum melangkah lebih jauh tetapi Anda dapat mencoba kueri di bawah ini :
Kueri :
db.collection.aggregate([
/** sort on `time` field */
{ $sort: { time: 1 } },
/** Convert string format of `time` field to milliseconds & store to `convertedTime` field for each doc */
{ $addFields: { convertedTime: { $toLong: { $dateFromString: { dateString: "$time" } } } } },
/** Group without condition to push all documents into `docs` array */
{
$group: { _id: "", docs: { $push: "$$ROOT" } }
},
/** re-creating `docs` array */
{
$project: {
_id: 0,
docs: {
$reduce: {
input: { $slice: [ "$docs", 1, { $size: "$docs" } ] }, /** Pick `docs` array without first element for iteration */
initialValue: { docObj: [ { $arrayElemAt: [ "$docs", 0 ] } ], previousTime: { $arrayElemAt: [ "$docs.convertedTime", 0 ] } },
in: {
docObj: { $concatArrays: [ "$$value.docObj", [
{ $mergeObjects: [ "$$this", { time_difference: { $divide: [ { $subtract: [ "$$this.convertedTime", "$$value.previousTime" ] }, 1000 ] } } ] }
]
]
},
previousTime: "$$this.convertedTime" // Store current doc's time to `previousTime` to utilize for next record
}
}
}
}
},
{
$unwind: { path: "$docs.docObj" }
},
/** Remove additionally added field */
{
$project: { "docs.docObj.convertedTime": 0 }
},
/** Replace root of the doc with `docs.docObj` */
{
$replaceRoot: { newRoot: "$docs.docObj" }
}
])
Uji : mongoplayground
Ref : aggregation-pipeline
Catatan : Kueri ini tidak akan menambahkan "time_difference" :null
untuk dokumen pertama tetapi untuk berjaga-jaga jika diperlukan coba ini di initialValue
:docObj: [ {$mergeObjects :[ { $arrayElemAt: [ "$docs", 0 ] }, { "time_difference" :null } ] ]
. Saya juga menyarankan untuk membatasi operasi ini pada dokumen tertentu dalam koleksi menggunakan $match
sebagai tahap pertama, daripada melakukan kueri ini pada semua dokumen menyebabkan
{
$group: { _id: "", docs: { $push: "$$ROOT" } }
}
itu sendiri akan menjadi hal yang besar jika dilakukan pada seluruh koleksi dengan kumpulan data yang besar.