MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Множество полета, където ключовете в документа варират Средно агрегиране

Очертание на концепцията

Това, което всъщност казах в много краткия коментар, е, че вместо това за издаване на отделна заявка за агрегиране за всяко име на "ключ" на сензора, можете да го поставите в ONE , стига да изчислите правилно "средните стойности".

Разбира се, проблемът във вашите данни е, че "ключовете" не присъстват във всички документи. Така че, за да получим правилната „средна стойност“, не можем просто да използваме $avg тъй като ще преброи "ВСИЧКИ" документи, независимо дали ключът присъства или не.

Затова вместо това разбиваме „математиката“ и правим $group за общия Count и обща Sum на всеки ключ първо. Това използва $ifNull за тестване за наличие на полето, а също и $cond за редуване на стойности за връщане.

.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 е "троичен" оператор, което означава, че първото условие "if" е true , "then" се връща вторият аргумент, "else" се връща третият аргумент.

Така че точката на троичния елемент в "Count" е да тренирате:

  • Ако полето е там, върнете 1 за броя
  • В противен случай върнете 0, когато не е там

След $group е направено, за да получите Average използваме $divide върху двете числа, произведени за всеки ключ в отделен $project етап.

Крайният резултат е „средната стойност“ за всеки ключ, който предоставяте, и това се счита само за добавяне на стойности и броене за документи, където полето действително присъства.

Така че поставянето на всички ключове в един оператор за агрегиране ще ви спести много време и ресурси за обработка.

Динамично генериране на конвейер

Така че, за да направите това „динамично“ в python, започнете със списъка:

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]

Което генерира същото като пълния списък по-горе за даден списък от „сензори“.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. node js mongodb премахване на ключ за грешка $lte не трябва да започва с '$'

  2. Възможно ли е да промените TimeZone по подразбиране в MongoDB с помощта на Rails 3?

  3. SQL RPAD()

  4. Как да стартирате mongo db на windows

  5. Премахване на дубликати от база данни MongoDB 4.2