Bạn đã viết tất cả các giai đoạn, Nhưng vấn đề ở đây là không có mối quan hệ nào giữa cái này với cái khác, Có nghĩa là những thay đổi được thực hiện ở thiết lập trước sẽ không được phản ánh trong các bước tiếp theo. Một số vấn đề:
{$sort: {$dateFromString:{time: 1}}} // You can't use `$dateFromString` in sort stage. Also syntax of `$dateFromString` is incorrect.
Giả sử nếu nó hoạt động (nó sẽ không nhưng giả sử) bạn không thực sự chuyển đổi time
&lưu trữ thời gian đã chuyển đổi thành một biến để sử dụng sau này trong $group
hoặc các giai đoạn tiếp theo. Vì vậy, bạn cần lưu trữ nó vào một biến trong tài liệu tương ứng bằng cách sử dụng $addFields
hoặc $project
. Tôi chưa đi sâu hơn nhưng bạn có thể thử truy vấn bên dưới:
Truy vấn:
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" }
}
])
Kiểm tra: mongoplayground
Tham khảo: tổng hợp-đường ống
Lưu ý: Truy vấn này sẽ không thêm "time_difference" :null
cho tài liệu đầu tiên nhưng trong trường hợp cần thiết, hãy thử điều này trong initialValue
:docObj: [ {$mergeObjects :[ { $arrayElemAt: [ "$docs", 0 ] }, { "time_difference" :null } ] ]
. Ngoài ra, tôi khuyên bạn nên giới hạn thao tác này đối với một số tài liệu nhất định trong bộ sưu tập bằng cách sử dụng $match
như giai đoạn đầu tiên, thay vì thực hiện truy vấn này trên tất cả các tài liệu gây ra
{
$group: { _id: "", docs: { $push: "$$ROOT" } }
}
bản thân nó sẽ là một thứ rất lớn khi nó được thực hiện trên toàn bộ bộ sưu tập với tập dữ liệu khổng lồ.