node

node

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
javascript/jQuery

javascript/jQuery

一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。
MongoDB

MongoDB

MongoDB 是一个基于分布式文件存储的数据库
openstack

openstack

OpenStack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。
VUE

VUE

一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。
bootstrap

bootstrap

Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.
HTML

HTML

超文本标记语言,标准通用标记语言下的一个应用。
CSS/SASS/SCSS/Less

CSS/SASS/SCSS/Less

层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。
PHP

PHP

PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执
每天进步一点点

每天进步一点点

乌法把门的各累笑寂静
求职招聘

求职招聘

猎头招聘专用栏目
Python

Python

一种解释型、面向对象、动态数据类型的高级程序设计语言。

MongoDB 聚合统计

lopo1983 发表了文章 • 0 个评论 • 584 次浏览 • 2018-09-14 14:56 • 来自相关话题

聚合(aggregate)主要用于计算数据,类似sql中的sum(),avg()。
db.集合名称.aggregate({管道:{表达式}})
?管道
?
管道在Unix和Linux中一般用于将当前命令的输出结果作为下一个命令的输入 在mongodb中,管道具有同样的作用,文档处理完毕后,通过管道进行下一次处理 常用管道
$group:将集合中的文档分组,可用于统计结果$match:过滤数据,只输出符合条件的文档$project:修改输入文档的结构,如重命名、增加、删除字段、创建计算结果$sort:将输入文档排序后输出$limit:限制聚合管道返回的文档数$skip:跳过指定数量的文档,并返回余下的文档$unwind:将数组类型的字段进行拆分
?
?
表达式
?
处理输入文档并输出
?
$sum:计算总和?
$avg:计算平均值?
$min:获取最小值?
$max:获取最大值?
$push:在结果文档中插入值到一个数组中?
$first:根据资源文档的排序获取第一个文档数据?
$last:根据资源文档的排序获取最后一个文档数据?
例子
表结构:
const compAccountDealrecordSchema = new Schema({
// billing 订单标识
numer: {
type: String
},
// 公司名称
_comp: {
type: Schema.Types.ObjectId,
ref: 'Company',
required: true,
index: true
},
// 消费金额
amount: {
type: Number,
default: 0.00
},
// 账户余额
balance: {
type: Number,
default: 0.00
},
// 渠道类型
channelType: {
type: String,
default: 'BALANCE'
},
// 日账单
dailyBill: {
type: Boolean,
default: false
},
// 按需扣费账单
debtDeduct: {
type: Boolean,
default: false
},
// 描述
detail: {
type: String,
default: ''
},
// 账单
detailRequest: {
type: Schema.Types.ObjectId,
ref: 'Company',
},
// 账单类型
detailType: {
type: String,
default: 'LINK'
},
// 账单链接
detailUrl: {
type: String,
default: ''
},
// 订单ID
orderId: {
type: Schema.Types.ObjectId,
ref: 'comp_account_billing_order'
},
// 账单产品详细
serviceItem: [],
// 产品类型
serviceType: {},
// 交易类型 [RECHARGE:收入,CONSUME:支出]
transactionType: {
type: String,
default: 'CONSUME'
},
// 备注
remark: {

}
}, {
timestamps: {
createdAt: 'created',
updatedAt: 'updated'
}
});静态方法
compAccountDealrecordSchema.statics = {
getAll: async function(queryMix, _comp) {
const {
querys,
select
} = queryMix;
const models = this.find({
...!!_comp && {
_comp
}
})
.sort({
'_id': -1,
});
try {
return {
data: {
result: await models,
totalCount: await models.count()
}
};
} catch (error) {
return error
}
},
getOne: async function(_id, _comp) {
const MODELS = this.findOne({..._comp && {
_comp
},
_id
}).sort({
'_id': -1
});
try {
return {
data: await MODELS
}
} catch (error) {
return error
}
},
createOne: async function(bodys) {
return await this.create(bodys)
},
backCashAdd: async function(bodys, auth) {
const {
_comp,
serviceBillCash,
serviceBillChannel,
serviceBillRemark
} = bodys
// 生成流水
await this.create({
'_comp': _comp,
'serviceBillProduct': '-',
'serviceBillType': '充值',
'serviceBillCash': `+${serviceBillCash}`,
'serviceBillChannel': `${serviceBillChannel}`,
'serviceBillRemark': `手工入款/n${serviceBillChannel}/n${serviceBillRemark}`,
'_admin': auth.id
});
return await ctx.model.Company.cashFN(serviceBillCash, auth, 'cash', 'add', _comp);
},
seachComp: async function(name) {
return await ctx.model.Company.find({
'compName': eval(`/${name}.*/i`)
}, {
'compEmail': 1,
'compName': 1,
'compPhone': 1
})
},
// 图表数据
/**
*
* @param {*} type 订单类型
* @param {*} scope 月份计算
* @param {*} _comp
*/
getPanelChart: async function(type = 'all', classify = "line", _comp) {
const MODEL = this.aggregate([
...classify === 'pie' ? [{
$unwind: `$serviceItem`,
}] : [],
...[{
$match: {
'_comp': mongoose.Types.ObjectId(_comp),
'created': {
"$gt": new Date(subtractMoment(1, 'month'))
},
"channelType": "CASH",
...type !== 'all' && {
'serviceItem.serviceType': type
}
}
},
{
$project: {
'_comp': 1,
'amount': 1,
'created': 1,
"serviceItem": 1,
'day': {
$substr: ["$created", 0, 10]
}
}
},
{
$group: {
...classify === "line" ? {
'_id': `$day`
} : {
'_id': '$serviceItem.serviceType'
},
'count': {
$sum: classify === 'pie' ? '$serviceItem.price' : '$amount'
}
}
},
{
$project: {
...classify === "line" ? {
'days': '$_id'
} : {
'serviceType': '$_id'
},
'count': 1,
_id: 0
}
},
{
$sort: {
'days': 1
}
}
]
]);
try {
const lastMonth = subtractMoment(1, 'month', 'subtract');
const DateMaps = (getDayAll(lastMonth, new Date()));
const data = await MODEL;
return {
...classify === 'pie' ? {
data
} : {
'data': {
datas: DateMaps.reduce((a, b) => {
let count;
data.forEach(e => {
if (e.days === b) count = e.count
});
a.push(count ? count : 0);
return a
}, []),
dates: DateMaps
}
}
}
} catch (error) {
console.log(error)
}
},
/**
* @param {String} type 产品类型()
*/
getCashCount: async function(ctx, auth, type, _comp) {
const {
endDate
} = ctx.helper.getPrevMoment('month');
const yestoday = ctx.helper.subtractMoment(1, 'day');
const typeoObj = type === 'all' ? {} : {
'serviceBillProduct': type,
'_comp': mongoose.Types.ObjectId(_comp ? _comp : auth.id)
};
return [(await this.aggregate([{
$match: {...typeoObj,
'created': {
"$gt": new Date(endDate)
},
'serviceBillType': '消费'
}
},
{
$group: {
'_id': {
'_comp': auth.id
},
'monthCashSum': {
$sum: "$serviceBillCash