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

Mehrere Felder, in denen die Schlüssel im Dokument von der durchschnittlichen Aggregation abweichen

Konzeptskizze

Was ich in dem sehr kurzen Kommentar im Grunde gesagt habe, ist das stattdessen zum Ausgeben einer separaten Aggregationsabfrage für jeden Sensor-"Schlüssel"-Namen können Sie ihn in ONE einfügen , solange Sie die "Durchschnitte" richtig berechnen.

Das Problem in Ihren Daten ist natürlich, dass die "Schlüssel" nicht in allen Dokumenten vorhanden sind. Um also den korrekten „Durchschnitt“ zu erhalten, können wir nicht einfach $avg da es "ALLE" Dokumente zählen würde, egal ob der Schlüssel vorhanden war oder nicht.

Stattdessen brechen wir die „Mathematik“ auf und machen einen $group für die Gesamt-Count und Gesamt Sum jeder Taste zuerst. Dies verwendet $ifNull um das Vorhandensein des Felds zu testen, und auch $cond zu alternativen zurückzugebenden Werten.

.aggregate([
  { "$match": {
    "$or": [
      { "Technique-Electrique_VMC Aldes_Power4[W]": { "$exists": True } },
      { "Technique-Electrique_VMC Unelvent_Power5[W]": { "$exists": True } }
    ]
  }}
  { "$group":{
    "_id":{
      "year":{ "$year":"$timestamp" },
      "month":{ "$month":"$timestamp" }
    },
    "Technique-Electrique_VMC Aldes_Power4[W]-Sum": { 
      "$sum": { 
        "$ifNull": [ "$Technique-Electrique_VMC Aldes_Power4[W]", 0 ]
      }
    },
    "Technique-Electrique_VMC Aldes_Power4[W]-Count": { 
      "$sum": { 
        "$cond": [
          { "$ifNull": [ "$Technique-Electrique_VMC Aldes_Power4[W]", false ] },
          1,
          0
        ]
      }
    },
    "Technique-Electrique_VMC Unelvent_Power5[W]-Sum": {
      "$sum": { 
        "$ifNull": [ "$Technique-Electrique_VMC Unelvent_Power5[W]", 0 ]
      }
    },
    "Technique-Electrique_VMC Unelvent_Power5[W]-Count": {
      "$sum": {
        "$cond": [ 
          { "$ifNull": [ "$Technique-Electrique_VMC Unelvent_Power5[W]", false ] },
          1,
          0
        ]
      }
    }
  }},
  { "$project": {
    "Technique-Electrique_VMC Aldes_Power4[W]-Avg": {
      "$divide": [
        "$Technique-Electrique_VMC Aldes_Power4[W]-Sum",
        "$Technique-Electrique_VMC Aldes_Power4[W]-Count"
      ]
    },
    "Technique-Electrique_VMC Unelvent_Power5[W]-Avg": {
      "$divide": [
        "Technique-Electrique_VMC Unelvent_Power5[W]-Sum",
        "Technique-Electrique_VMC Unelvent_Power5[W]-Count"
      ]
    }
  }}
])

Der $cond operator ist ein "ternärer" Operator, was bedeutet, dass die erste "if"-Bedingung true ist , "then" wird das zweite Argument zurückgegeben, "else" wird das dritte Argument zurückgegeben.

Also der Punkt des Ternären im "Count" ist zu erarbeiten:

  • Wenn das Feld vorhanden ist, geben Sie 1 für count zurück
  • Gib andernfalls 0 zurück, wenn es nicht vorhanden ist

Nach dem $group getan, um den Average zu erhalten wir verwenden $divide auf den zwei Zahlen, die für jeden Schlüssel innerhalb eines separaten $project Stufe.

Das Endergebnis ist der "Durchschnitt" für jeden Schlüssel, den Sie angeben, und dabei wurden nur Werte und Zählungen für Dokumente hinzugefügt, in denen das Feld tatsächlich vorhanden war.

Wenn Sie also alle Schlüssel in eine Aggregationsanweisung einfügen, sparen Sie viel Zeit und Ressourcen bei der Verarbeitung.

Dynamische Generierung der Pipeline

Um dies "dynamisch" in Python zu tun, beginnen Sie mit der Liste:

sensors = ["Technique-Electrique_VMC Aldes_Power4[W]", "Technique-Electrique_VMC Unelvent_Power5[W]"]

match = { '$match': { '$or': map(lambda x: { x: { '$exists': True } },sensors) } }

group = { '$group': { 
  '_id': {
    'year': { '$year': '$timestamp' },
    'month': { '$month':'$timestamp' }
  }
}}

project = { '$project': {  } }

for k in sensors:
  group['$group'][k + '-Sum'] = {
    '$sum': { '$ifNull': [ '$' + k, 0 ] }
  }
  group['$group'][k + '-Count'] = {
    '$sum': { '$cond': [ { '$ifNull': [ '$' + k, False ] }, 1, 0 ]  }
  }
  project['$project'][k + '-Avg'] = {
    '$divide': [ '$' + k + '-Sum', '$' + k + '-Count' ]
  }

pipeline = [match,group,project]

Das erzeugt dasselbe wie die vollständige Liste oben für eine gegebene Liste von "Sensoren".