MongoDB

Daten in MongoDB Atlas aufbereiten

In unserem dritten Artikel der Serie “Von der CSV-Datei zur Chart mit MongoDB Atlas” bereiten wir die zuvor importierten Daten auf Tages- und Stundenbasis auf und berechnen gleichzeitig einige Kennzahlen, wie beispielsweise den 7- und 30-Tagesdurchschnitt der erzeugten Werte. Diese helfen uns in der Chart dabei, Trends zu erkennen. Durch die zuvor aufbereiteten Daten können die Charts ohne große Vorberechnung direkt auf vorhandenen Daten starten.

Die Rahmenbedingungen

Wir gehen davon aus, dass der letzte Tag in den CSV-Dateien jeweils noch nicht abgeschlossen ist. In den Charts wollen wir nur vollständig vorhandene Tage anzeigen, so dass wir die Datenaufbereitung nur bis zum vorletzten Tag durchführen. Durch diese Rahmenbedingung reicht die Aufbereitung der Daten einmal am Tag, so dass der zuständige Trigger nur täglich laufen muss.

Bei der Aufbereitung kommen komplexe Aggregation-Pipelines zum Einsatz; um den Speicherbedarf in Grenzen zu halten, werden die Kennzahlen nur für die letzten 30 Tage neu berechnet; historische Daten bleiben in der Collection, werden aber nicht mehr aktualisiert. Dies ist insbesondere bei Einsatz eines Shared Clusters (M0, M2, M5) wichtig, weil in diesen die Aggregation-Pipeline keinen Zugriff auf die Disk hat (Option allowDiskUse); zur sparsamen Ressourcen-Verwendung ist es jedoch auch bei anderen Clustergrößen sinnvoll, nur die notwendigen Daten einzubeziehen. Um den gleitenden 30-Tage-Durchschnitt berechnen zu können, werden die Daten der letzten 60 Tage einbezogen.

Regelmäßige Datenaufbereitung

Auch in diesem Fall kommt ein Trigger zum Einsatz, der jedoch im Gegensatz zum Import-Trigger auf täglicher Basis läuft. Da die Daten anhand des zuletzt importierten Datums frühzeitig in der Aggregation-Pipeline eingeschränkt werden sollen, haben wir in diesem Fall auf eine View verzichtet. Dadurch wird das Skript des Triggers länger, durch die frühzeitige Filterung ist es jedoch möglich, auf Indexe zu setzen und die Daten effizient zu selektieren.

Neben der beschriebenen Datenaufbereitung werden außerdem die Daten für zwei Heatmaps vorbereitet, die einen Überblick über die Verteilung der Generierung und der Last in Bezug auf Wochentage und Stunden geben sollen.

Der folgende Überblick zeigt grob die Struktur des Skripts im Trigger:

exports = async function () {
  const serviceName = "Logger";
  const databaseName = "Energy";
  const collectionName = "pv_view_enriched";
  const collection = context.services
    .get(serviceName)
    .db(databaseName)
    .collection(collectionName);

  try {
    // Get last imported date
    const last = await collection
      .find({}, { date: 1, _id: 0 })
      .sort({ date: -1 })
      .limit(1)
      .toArray();
    if (last && last.length > 0) {
      await collection
        .aggregate([
          // ... Aggregate data by day
          {
            $merge: {
              into: "pv_dailyStats",
              on: "_id",
            },
          },
        ])
        .toArray();
      await collection
        .aggregate([
          // ... Aggregate data by hour
          {
            $merge: {
              into: "pv_hourlyStats",
              on: "_id",
            },
          },
        ])
        .toArray();
      await collection
        .aggregate([
          // Group data by weekday and hour to prepare heat map
          {
            $merge: {
              into: "pv_heatMapDayHour",
            },
          },
        ])
        .toArray();
    }
  } catch (err) {
    console.log("error performing aggregation: ", err.message);
  }
};

Genauere Informationen zur Berechnung der einzelnen Kennzahlen finden Sie bei uns im Blog, u.a. im Artikel Einen gleitenden Durchschnitt mit MongoDB berechnen.

Nach der Aggregation haben wir auf täglicher Basis folgende Daten vorliegen:

{
  "_id": {
    "$date": "2024-03-18T00:00:00.000Z"
  },
  "count": {
    "$numberLong": "288"
  },
  "energy_kWh": {
    "bat": -1.5406234166666668,
    "dc": 7.764739166666667,
    "dcA": 2.9326225833333335,
    "dcB": 4.832116583333334,
    "grid": 0.5535336666666667,
    "gridFeed": 0.5785900833333334,
    "gridLoad": 0.025056416666666668,
    "load": 5.289126083333334
  },
  "power_kW": {
    // ...
    "dc": {
      "min": 0,
      "max": 1.8013240000000001,
      "avg": 0.3235307986111111
    },
    // ...
    "load": {
      "min": 0.102882,
      "max": 1.818604,
      "avg": 0.22038025347222223
    }
  },
  "soc": {
    "min": 40.33886,
    "max": 96.89892,
    "avg": 69.87854081944445
  },
  // ...
  "trends": {
    "7days": {
      "dc": {
        "avg": 15.761449761904762,
        "min": 7.764739166666667,
        "max": 24.218373166666666
      },
      "load": {
        // ...
      },
      "gridFeed": {
        // ...
      }
    },
    "30days": {
      // ...
    }
  },
  "complete": true
}

Fazit

Diese Daten bieten eine gute Ausgangsbasis, um unsere Charts darauf aufzusetzen. Wichtig ist bei der Aufbereitung, die Datenmenge auf das notwendige zu beschränken, um das Cluster nicht unnötig zu belasten. Auch das Aufbereitungsintervall sollte passend zur Aktualisierungsrate gewählt werden.

Nach diesen Vorbereitungen unter der Haube unseres MongoDB Atlas Clusters wenden wir uns im letzten Teil der Serie der Erstellung der Charts zu und werden mit einem Dashboard belohnt, das unsere Daten übersichtlich darstellt.


MongoDB MongoDB Atlas CSV Triggers Charts
Markus Wildgruber
Markus Wildgruber

Geschäftsführer

  • CloudArchitect
  • DeveloperCoach
  • DotNet
  • MongoDB
  • Angular

Dieser Artikel ist Teil der Serie Von der CSV-Datei zur Chart mit MongoDB Atlas
  1. Von der CSV-Datei zur Chart mit MongoDB Atlas
  2. CSV-Daten in MongoDB Atlas importieren
  3. Daten in MongoDB Atlas aufbereiten
  4. Charts in MongoDB Atlas aufsetzen