sql >> Databáze >  >> NoSQL >> MongoDB

Více polí, kde se klíče v dokumentu liší Průměrná agregace

Nástin konceptu

To, co jsem v podstatě řekl ve velmi krátkém komentáři, je, že místo pro zadání samostatného agregačního dotazu pro každý název „klíče“ senzoru jej můžete vložit do JEDNOHO , pokud správně vypočítáte „průměry“.

Samozřejmě problém ve vašich datech je, že "klíče" nejsou přítomny ve všech dokumentech. Abychom získali správný „průměr“, nemůžeme jednoduše použít $avg protože by počítal „VŠECHNY“ dokumenty, ať už byl klíč přítomen nebo ne.

Takže místo toho rozdělíme "matematický" a provedeme $group pro celkový Count a celkový Sum od každého klíče jako první. Toto používá $ifNull otestovat přítomnost pole a také $cond pro alternativní hodnoty pro návrat.

.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"
      ]
    }
  }}
])

$cond Operátor je "ternární" operátor, což znamená, že první podmínka "if" je true , "pak" je vrácen druhý argument, "else" je vrácen třetí argument.

Tedy bod trojky v "Count" je cvičit:

  • Pokud tam pole je, vraťte 1 jako počet
  • Jinak vraťte 0, když tam není

Po $group je hotovo, abyste získali Average používáme $divide na dvou číslech vytvořených pro každý klíč v samostatném $project fázi.

Konečným výsledkem je „průměr“ pro každý klíč, který zadáte, a to uvažovalo pouze o přidání hodnot a počtů pro dokumenty, kde se pole skutečně nacházelo.

Takže umístění všech klíčů do jediného agregačního příkazu vám ušetří spoustu času a prostředků na zpracování.

Dynamické generování potrubí

Chcete-li to provést "dynamicky" v pythonu, začněte se seznamem:

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]

Což generuje totéž jako úplný seznam výše pro daný seznam „senzorů“.




  1. počítat mongodb v php

  2. $elemMatch projekce v node.js

  3. Redis – Jak nakonfigurovat vlastní konverze

  4. MongoDB:Jak zjistit n-tý nejvyšší plat z inkasa