2016-08-05 47 views
2

Kann jemand Aggregatfunktionen erstellen, zum Beispiel avg, sum, max und min in der PouchDB-Datenbank. Ich habe eine einfache Anwendung zum Testen der PouchDB erstellt. Ich habe immer noch nicht herausgefunden, wie man diese Befehle ausführt. Danke im Voraus.Wie simuliert man die Aggregatfunktionen avg, sum, max, min und count auf PouchDB?

Zum Beispiel. Wie erhält man den höchsten, niedrigsten oder durchschnittlichen Wert für das Feld "Zahl"?

Mein Haupt Ionic 2 Komponente

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); 
+0

Durch was? Summe von was? Max und Min von was? Möchten Sie diese Werte in einer Variablen speichern (oder einfach nur "console.log")? – acdcjunior

+0

Es könnte auf der Konsole angezeigt werden. Zum Beispiel größer, kleiner, Summe, Durchschnittswert im Feld "Nummer" gespeichert. Zum Beispiel ist der größte Wert in der "Nummer" => 'Nummer': 13. Dies kann auf der Konsole angezeigt werden. – fenix

Antwort

2

Sie of the db.query() method from PouchDB die map/reduce Funktionen verwenden können, die durchschnittliche, Summe zu erhalten, größte oder jede andere Art von Aggregation der docs.

Ich habe eine demo JSBin fiddle with a running example erstellt. Ich habe die Erklärung der Funktionen direkt in den Code (unten) als Kommentare eingefügt, da ich dachte, es wäre einfacher.

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); 
    }); 
} 

Hinweis: Dies ist nur eine Möglichkeit, es zu tun. Es gibt mehrere andere Möglichkeiten (keine IDs als Schlüssel auszugeben, Gruppen und verschiedene Reduce-Funktionen zu verwenden, integrierte Reduce-Funktionen wie _sum, ...), ich dachte einfach, dass dies die allgemein einfachere Alternative ist.

+0

Wow, das ist erstaunlich, ich hatte schon die Hoffnung verloren! Vielen Dank, @acdcjunior – fenix

0

Ich bin ein Fan von views in PouchDB für solche Probleme.

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

Es ist möglich, eine gespeicherte Ansicht zu erstellen, die Sie mit dem gleichen Index mehrmals erneut abfragen kann: was bedeuten, während das erste Mal durch langsames (Scan) ist, später Abfragen wesentlich schneller als die Daten sein wurde bereits indiziert.

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); 
}); 

Notierte die Zugabe des Blicks auf die Daten, die Sie in Ihre Datenbank zu laden, sowie die Tatsache, dass die Karte und reduziert requried in Strings umgewandelt werden (die .toString() am Ende der Funktion)

3

Die höchsten und niedrigsten Werte der Zahlenfelder sind über die integrierte Reduzierfunktion _stats abrufbar.

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 
}); 

Das Ergebnis sieht ähnlich wie:

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

Der höchste Wert in dem "max" -Feld, die niedrigste in der "min" -Feld. Jetzt müssen Sie nur noch Ihre gewünschte durchschnittliche berechnen, beispielsweise der Mittelwert:

var meanAverage = result.sum/result.count; 

Andere built-in reduce functions in PouchDB sind _count und _sum.

Die PouchDB documentation sagt folgendes über Funktionen reduzieren:

Tipp: Wenn Sie nicht über einen eingebauten in Verwendung, sind Sie wahrscheinlich etwas falsch gemacht.