簡體   English   中英

如何模擬PouchDB上的聚合函數avg,sum,max,min和count?

[英]How to simulating the aggregate functions avg, sum, max, min, and count on PouchDB?

有誰知道如何在PouchDB數據庫上創建聚合函數,例如avg,sum,max和min。 我創建了一個簡單的應用程序來測試PouchDB。 我還沒弄明白如何運行這些命令。 提前致謝。

例如。 您如何獲得“數字”字段的最高,最低或平均值?

我的主要Ionic 2組件

import {Component} from '@angular/core';
import {Platform, ionicBootstrap} from 'ionic-angular';
import {StatusBar} from 'ionic-native';
import {HomePage} from './pages/home/home';
declare var require: any;
var pouch = require('pouchdb');
var pouchFind = require('pouchdb-find');
@Component({
    template: '<ion-nav [root]="rootPage"></ion-nav>'
})
export class MyApp {
    rootPage: any = HomePage;
    db: any;
    value: any;
    constructor(platform: Platform) {
        platform.ready().then(() => {
            StatusBar.styleDefault();
        });
        pouch.plugin(pouchFind);
        this.db = new pouch('friendsdb');
        let docs = [
            {
                '_id': '1',
                'number': 10,
                'values': '1, 2, 3',
                'loto': 'fooloto'
            },
            {
                '_id': '2',
                'number': 12,
                'values': '4, 7, 9',
                'loto': 'barloto'
            },
            {
                '_id': '3',
                'number': 13,
                'values': '9, 4, 5',
                'loto': 'fooloto'
            }
        ];
        this.db.bulkDocs(docs).then(function (result) {
            console.log(result);
        }).catch(function (err) {
            console.log(err);
        });
    }
}
ionicBootstrap(MyApp);

可以使用內置的_stats reduce函數檢索數字字段的最高值和最低值。

var myMapReduceFun = {
  map: function (doc) {
    emit(doc._id, doc.number);
  },
  reduce: '_stats'
};

db.query(myMapReduceFun, {reduce: true}).then(function (result) {
  // handle result
}).catch(function (err) {
  // handle errors
});

結果看起來類似於:

{"sum":35,"count":3,"min":10,"max":13,"sumsqr":214}

最高值在“最大”字段中,“最小”字段中最低。 現在你只需要計算你想要的平均值,例如平均值:

var meanAverage = result.sum / result.count;

PouchDB中的其他內置reduce函數是_count和_sum。

PouchDB文檔說明了以下關於reduce函數的內容:

提示:如果您沒有使用內置功能,那么您可能做錯了。

您可以使用PouchDB中db.query()方法map / reduce函數來獲取文檔的平均值,總和,最大值或任何其他類型的聚合。

用一個運行的例子創建了一個演示JSBin小提琴 我將函數的解釋直接添加到代碼(下面)作為注釋,因為我認為它更簡單。

var db = new PouchDB('friendsdb');
var docs = [
      {'_id': '1', 'number': 10, 'values': '1, 2, 3', 'loto': 'fooloto'},
      {'_id': '2', 'number': 12, 'values': '4, 7, 9', 'loto': 'barloto'},
      {'_id': '3', 'number': 13, 'values': '9, 4, 5', 'loto': 'fooloto'}
];

db.bulkDocs(docs).then(function(result) {
  querySum();
  queryLargest();
  querySmallest();
  queryAverage();
}).catch(function(err) {
  console.log(err);
});

function querySum() {
  function map(doc) {
    // the function emit(key, value) takes two arguments
    // the key (first) arguments will be sent as an array to the reduce() function as KEYS
    // the value (second) arguments will be sent as an array to the reduce() function as VALUES
    emit(doc._id, doc.number);
  }
  function reduce(keys, values, rereduce) {
    // keys:
    //   here the keys arg will be an array containing everything that was emitted as key in the map function...
    //   ...plus the ID of each doc (that is included automatically by PouchDB/CouchDB).
    //   So each element of the keys array will be an array of [keySentToTheEmitFunction, _idOfTheDoc]
    //
    // values
    //   will be an array of the values emitted as value
    console.info('keys ', JSON.stringify(keys));
    console.info('values ', JSON.stringify(values));
    // check for more info: http://couchdb.readthedocs.io/en/latest/couchapp/views/intro.html


    // So, since we want the sum, we can just sum all items of the values array
    // (there are several ways to sum an array, I'm just using vanilla for to keep it simple)
    var i = 0, totalSum = 0;
    for(; i < values.length; i++){
        totalSum += values[i];
    }
    return totalSum;
  }
  db.query({map: map, reduce: reduce}, function(err, response) {
    console.log('sum is ' + response.rows[0].value);
  });
}

function queryLargest() {
  function map(doc) {
    emit(doc._id, doc.number);
  }
  function reduce(keys, values, rereduce) {
    // everything same as before (see querySum() above)
    // so, this time we want the larger element of the values array

    // http://stackoverflow.com/a/1379560/1850609
    return Math.max.apply(Math, values);
  }
  db.query({map: map, reduce: reduce}, function(err, response) {
    console.log('largest is ' + response.rows[0].value);
  });
}

function querySmallest() {
  function map(doc) {
    emit(doc._id, doc.number);
  }
  function reduce(keys, values, rereduce) {
    // all the same... now the looking for the min
    return Math.min.apply(Math, values);
  }
  db.query({map: map, reduce: reduce}, function(err, response) {
    console.log('smallest is ' + response.rows[0].value);
  });
}

function queryAverage() {
  function map(doc) {
    emit(doc._id, doc.number);
  }
  function reduce(keys, values, rereduce) {
    // now simply calculating the average
    var i = 0, totalSum = 0;
    for(; i < values.length; i++){
        totalSum += values[i];
    }
    return totalSum/values.length;
  }
  db.query({map: map, reduce: reduce}, function(err, response) {
    console.log('average is ' + response.rows[0].value);
  });
}

注意:這只是一種方法。 還有其他幾種可能性(不使用ID作為鍵,使用組和不同的reduce函數,使用內置的reduce函數,例如_sum,...),我只是認為這是一般說來的更簡單的替代方法。

我喜歡PouchDB中有關此類問題的views

https://pouchdb.com/2014/05/01/secondary-indexes-have-landed-in-pouchdb.html

可以創建一個存儲視圖,允許您多次重新查詢相同的索引:這意味着第一次通過時速度很慢(完全掃描),后面的查詢將會更快,因為數據已被索引。

var db = new PouchDB('friendsdb');

var view = {
  '_id':'_design/metrics',
  'views':{
    'metrics':{
      'map':function(doc){
        // collect up all the data we are looking for
        emit(doc._id, doc.number);
      }.toString(),
      'reduce':function(keys, values, rereduce){
        var metrics = {
          sum:0,
          max:Number.MIN_VALUE,
          min:Number.MAX_VALUE,
          count:0
        };
        // aggregate up the values
        for(var i=values.length-1; i>=0; i--){
          var v = values[i];
          metrics.sum += v;
          metrics.max = (metrics.max < v) ? v : metrics.max;
          metrics.min = (metrics.min < v) ? metrics.min : v;
          metrics.count += v.count || 1;
        }
        metrics.avg = metrics.sum/metrics.count;
        return metrics;
      }.toString()
    }
  }
};

// alternately you could use a built in reduce
// if one already exists for the aggregation 
// you are looking for
//view.reduce = '_stats';

// note the addition of the view
var docs = [view
  ,{'_id':'1','number':10,'values':[1,2,3],'loto':'fooloto'}
  ,{'_id':'2','number':12,'values':[4,7,9],'loto':'barloto'}
  ,{'_id':'3','number':13,'values':[9,4,5],'loto':'fooloto'}
];

db.bulkDocs(docs).then(function(result) {
  db.query('metrics',{reduce:true},function(err, response) {
    var m = response.rows[0].value;
    console.log('smallest.: ' + m.min);
    console.log('largest..: ' + m.max);
    console.log('average..: ' + m.avg);
    console.log('count....: ' + m.count);
    console.log('Total ...: ' + m.sum);
  });
}).catch(function(err) {
  console.log(err);
});

請注意,將視圖添加到加載到數據庫中的數據,以及需要將map和reduce轉換為字符串(函數末尾的.toString()這一事實

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM