Du har skrevet alle stadierne, men sagen her er, at der ikke er nogen relation mellem den ene til den anden. Betyder, at ændringer, der er foretaget ved tidligere opsætning, ikke afspejles i de næste trin. Et par problemer:
{$sort: {$dateFromString:{time: 1}}} // You can't use `$dateFromString` in sort stage. Also syntax of `$dateFromString` is incorrect.
Lad os antage, at hvis det virkede (det vil det ikke, men antage ), at du faktisk ikke konverterer time
&lagring af konverteret tid til en variabel til senere brug i $group
eller længere nede i etaper. Så du skal gemme den til en variabel i det respektive dokument ved hjælp af $addFields
eller $project
. Jeg er ikke gået længere ned, men du kan prøve nedenstående forespørgsel :
Forespørgsel:
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
Ref : aggregation-pipeline
Bemærk: Denne forespørgsel ville ikke tilføje "time_difference" :null
for det første dokument, men for en sikkerheds skyld, hvis det er nødvendigt, prøv dette i initialValue
:docObj: [ {$mergeObjects :[ { $arrayElemAt: [ "$docs", 0 ] }, { "time_difference" :null } ] ]
. Jeg vil også foreslå at begrænse denne operation til visse dokumenter i samlingen ved hjælp af $match
som første trin, i stedet for at udføre denne forespørgsel på alle de dokumenter, der forårsager
{
$group: { _id: "", docs: { $push: "$$ROOT" } }
}
i sig selv vil være en kæmpe ting, når det er gjort på hele samlingen med et stort datasæt.