如何在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。我仍然不知道如何 运行 这些命令。提前致谢。
例如。如何获得 "number" 字段的最高、最低或平均值?
My main Ionic 2 component
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);
您可以使用 map
/reduce
函数 of the db.query()
method from PouchDB 获取文档的平均值、总和、最大值或任何其他类型的聚合。
我创建了一个 demo JSBin fiddle with a running example。我将功能的解释直接添加到代码(下面)中作为注释,因为我认为这样会更简单。
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
//
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()
)
可以使用内置的 _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}
最高值在 "max" 字段中,最低值在 "min" 字段中。现在你只需要计算你想要的平均值,例如平均平均值:
var meanAverage = result.sum / result.count;
PouchDB 中的其他 built-in reduce functions 是 _count 和 _sum。
PouchDB documentation 关于 reduce 函数的说明如下:
Tip: if you’re not using a built-in, you’re probably doing it wrong.
有谁知道如何在 PouchDB 数据库上创建聚合函数,例如 avg、sum、max 和 min。我创建了一个简单的应用程序来测试 PouchDB。我仍然不知道如何 运行 这些命令。提前致谢。
例如。如何获得 "number" 字段的最高、最低或平均值?
My main Ionic 2 component
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);
您可以使用 map
/reduce
函数 of the db.query()
method from PouchDB 获取文档的平均值、总和、最大值或任何其他类型的聚合。
我创建了一个 demo JSBin fiddle with a running example。我将功能的解释直接添加到代码(下面)中作为注释,因为我认为这样会更简单。
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
//
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()
)
可以使用内置的 _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}
最高值在 "max" 字段中,最低值在 "min" 字段中。现在你只需要计算你想要的平均值,例如平均平均值:
var meanAverage = result.sum / result.count;
PouchDB 中的其他 built-in reduce functions 是 _count 和 _sum。
PouchDB documentation 关于 reduce 函数的说明如下:
Tip: if you’re not using a built-in, you’re probably doing it wrong.