Gesamtwerte und prozentuale Anteile ermitteln
Interessiert man sich für den prozentualen Anteil eines Werts am Gesamtwert, leistet $setWindowFields gute Dienste. Mit dieser Aggregation Stage können Berechnungen innerhalb eines Bereichs von Dokumenten durchgeführt werden und das Ergebnis als Feld hinzugefügt werden. Also genau das, was wir brauchen, um den Anteil eines Werts am Gesamtwert ermitteln zu können.
Als Beispiel gehen wir von folgender Dokumentenstruktur aus, die jeweils einen Zeitstempel und einen Wert umfasst:
[{
"ts": ISODate("2023-09-20T00:00:00.000Z"),
"value": 100
},
{
"ts": ISODate("2023-09-21T00:00:00.000Z"),
"value": 150
},
{
"ts": ISODate("2023-09-24T00:00:00.000Z"),
"value": 50
},
{
"ts": ISODate("2023-09-26T00:00:00.000Z"),
"value": 10
}]
Folgende Aggregation-Pipeline berechnet den Gesamtwerts des value
-Felds:
[
{
$setWindowFields: {
partitionBy: null,
output: {
total: {
$sum: "$value",
window: {
documents: ["unbounded", "unbounded"],
},
},
},
},
},
]
Durch die Angabe von null
als Kriterium zur Bildung der Partitionen und unbounded
als Grenzen des Fensters, werden alle Dokumente einbezogen, so dass die Gesamtsumme gebildet wird.
Als Ergebnis werden folgende Dokumente geliefert:
[{
"ts": ISODate("2023-09-20T00:00:00.000Z"),
"value": 100,
"total": 310
},
{
"ts": ISODate("2023-09-21T00:00:00.000Z"),
"value": 150,
"total": 310
},
{
"ts": ISODate("2023-09-24T00:00:00.000Z"),
"value": 50,
"total": 310
},
{
"ts": ISODate("2023-09-26T00:00:00.000Z"),
"value": 10,
"total": 310
}]
Eine einfache $set
-Stage wird anschließend zum Berechnen des Anteils genutzt:
[
{
$setWindowFields: {
partitionBy: null,
output: {
total: {
$sum: "$value",
window: {
documents: ["unbounded", "unbounded"],
},
},
},
},
},
{
$set: {
pct: {
$divide: ["$value", "$total"],
},
},
},
]
Sollte es möglich sein, dass die Gesamtsumme den Wert Null ergibt, muss man den Ausdruck in der $set
-Stage erweitern, um zuvor zu prüfen, ob die Gesamtsumme gleich 0 ist und gegebenenfalls auf die Division verzichten. Damit ist man gegen eine Division durch 0 gewappnet.
Für unser Beispiel führt die Aggregation zu folgender Ausgabe:
[{
"ts": ISODate("2023-09-20T00:00:00.000Z"),
"value": 100,
"total": 310,
"pct": 0.3225806451612903
},
{
"ts": ISODate("2023-09-21T00:00:00.000Z"),
"value": 150,
"total": 310,
"pct": 0.4838709677419355
},
{
"ts": ISODate("2023-09-24T00:00:00.000Z"),
"value": 50,
"total": 310,
"pct": 0.16129032258064516
},
{
"ts": ISODate("2023-09-26T00:00:00.000Z"),
"value": 10,
"total": 310,
"pct": 0.03225806451612903
}]
Weitere Möglichkeiten
Durch die Verwendung des partitionBy
-Felds kann der Bereich eingeschränkt werden, für den die Gesamtsumme gebildet wird; wenn also beispielsweise verschiedene Sensoren berücksichtigt werden sollen oder die Tagessumme relevant ist, kann über eine geeignete Partitionierung die entsprechende Summe gebildet werden.
Fazit
Die Berechnung von prozentualen Anteilen ist nur ein Beispiel für die Möglichkeiten, die $setWindowFields
bietet. Weitere Artikel in dieser Serie zeigen zusätzliche Beispiele wie diese bei der Ermittlung von Kennzahlen eingesetzt werden können.
Geschäftsführer