Sie haben alle Phasen geschrieben, aber die Sache hier ist, dass es keine Beziehung zwischen ihnen gibt, bedeutet, dass Änderungen, die bei der vorherigen Einrichtung vorgenommen wurden, nicht in den nächsten Schritten widergespiegelt werden. Paar Probleme :
{$sort: {$dateFromString:{time: 1}}} // You can't use `$dateFromString` in sort stage. Also syntax of `$dateFromString` is incorrect.
Nehmen wir an, wenn es funktioniert hat (es wird nicht, aber davon ausgehen), dass Sie nicht wirklich time
konvertieren &Speichern der konvertierten Zeit in einer Variablen zur späteren Verwendung in $group
oder weiter unten Stufen. Sie müssen es also mit $addFields
in einer Variablen im jeweiligen Dokument speichern oder $project
. Ich bin nicht weiter nach unten gegangen, aber Sie können die folgende Abfrage versuchen:
Abfrage :
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" }
}
])
Test : mongoplayground
Referenz: aggregation-pipeline
Hinweis: Diese Abfrage würde "time_difference" :null
nicht hinzufügen für das erste Dokument, aber nur für den Fall, wenn es benötigt wird, versuchen Sie dies in initialValue
:docObj: [ {$mergeObjects :[ { $arrayElemAt: [ "$docs", 0 ] }, { "time_difference" :null } ] ]
. Außerdem würde ich vorschlagen, diese Operation mit $match
auf bestimmte Dokumente in der Sammlung zu beschränken als erste Stufe, anstatt diese Abfrage für alle Dokumente durchzuführen, die
{
$group: { _id: "", docs: { $push: "$$ROOT" } }
}
selbst wird eine riesige Sache sein, wenn es für die gesamte Sammlung mit riesigem Datensatz gemacht wird.