sql >> Database teknologi >  >> NoSQL >> MongoDB

Behov for at beregne dato- og klokkeslætsforskellen for feltet datetime gemt i strengformat i MongoDB

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.




  1. Fejl:nøgle $conditionalHandlers må ikke starte med '$' mongodb

  2. Indlejret Vælg Mongodb-forespørgselsfejl

  3. Gem relaterede nøgler som OID eller strenge i MongoDB

  4. Hvordan indstiller jeg standardværdien for et heltal i mongodb?