MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Sie müssen die Datetime-Differenz für das Datetime-Feld berechnen, das im String-Format in MongoDB gespeichert ist

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

verursachen
{
   $group: { _id: "", docs: { $push: "$$ROOT" } }
}

selbst wird eine riesige Sache sein, wenn es für die gesamte Sammlung mit riesigem Datensatz gemacht wird.