可以在查询汇总中获得月份,季度和半月的销售总额,或者我分别执行每个查询?有可能获得月份,季度和学期mongodb的查询销售额?
无论模型,我的问题是您是否可以在单个查询中获得所有信息,还是应该单独执行。
如果不是,那么获取这些信息的最佳方法是什么?
可以在查询汇总中获得月份,季度和半月的销售总额,或者我分别执行每个查询?有可能获得月份,季度和学期mongodb的查询销售额?
无论模型,我的问题是您是否可以在单个查询中获得所有信息,还是应该单独执行。
如果不是,那么获取这些信息的最佳方法是什么?
您可以使用aggregation framework做到这一点,如果map-reduce能够解决您手头的问题,那么它是首选,因为它通常都是可读的,速度更快。
当然,如何这条管道的样子取决于你的文档的形状(我还不知道),但计算一次所有三个总和应尽可能用$match阶段过滤下来的文件和$group阶段做总和计算。
在$group
阶段中,您可以使用$sum运算符与嵌套$cond运算符有条件地总结月份,季度和半年的值。
假设你有一个销售收取的是单据,
{ "_id": ObjectId("579d91a4e474b2af2f1ddc65"), "date": ISODate("2015-06-29T22:00:00Z"), "quantity": 1, "price": 30 }
{ "_id": ObjectId("579d9193e474b2af2f1ddc66"), "date": ISODate("2015-07-28T22:00:00Z"), "quantity": 3, "price": 20 }
{ "_id": ObjectId("579d91a4e474b2af2f1ddc67"), "date": ISODate("2015-08-29T22:00:00Z"), "quantity": 2, "price": 10 }
{ "_id": ObjectId("579d91a4e474b2af2f1ddc68"), "date": ISODate("2015-09-29T22:00:00Z"), "quantity": 4, "price": 15 }
{ "_id": ObjectId("579d919ee474b2af2f1ddc69"), "date": ISODate("2015-11-28T22:00:00Z"), "quantity": 2, "price": 20 }
配图,减少解决方案将
var mapFunc = function() {
date = this.date;
if (new ISODate("2015-06-01T00:00:00Z") <= date && date <= new ISODate("2016-01-01T00:00:00Z")) {
var totalPrice = this.quantity * this.price;
if (new ISODate("2015-11-01T00:00:00Z") <= date) emit ("lastMonth", totalPrice);
if (new ISODate("2015-09-01T00:00:00Z") <= date) emit ("lastQuarter", totalPrice);
emit("lastSemester", totalPrice);
}
}
var reduceFunc = function(key, values) {
return Array.sum(values);
}
db.sales.mapReduce(mapFunc, reduceFunc, { out: { inline : 1 } });
的结果是
"results" : [ { "_id" : "lastSemester", "value" : 210 },
{ "_id" : "lastMonth", "value" : 40 },
{ "_id" : "lastQuarter", "value" : 100 } ]
虽然,我不知道(并希望)知道如何通过聚合来实现此特定集合。
唯一事情,进入初衷是希望通过$group
月
db.corders.aggregate(
{ $match: { $and: [ { date: { $gte: new ISODate("2015-06-01T00:00:00Z") } }, { date : { $lte: new ISODate("2016-01-01T00:00:00Z") } } ] } },
{ $group: { "_id": { "$month": "$date" }, totalPrice: { $sum: { $multiply: [ "$price", "$quantity" ] } } } });
这给结果
{ "_id" : 11, "totalPrice" : 40 }
{ "_id" : 9, "totalPrice" : 60 }
{ "_id" : 8, "totalPrice" : 20 }
{ "_id" : 7, "totalPrice" : 60 }
{ "_id" : 6, "totalPrice" : 30 }
应进一步根据任务本地处理。
根据文档字段的具体情况,可以通过汇总框架,使用match
,project
和group
阶段的组合完成此操作。
举个例子,我将承担Sales
文件,以date
场和amount
领域,应当汇总以获取一定时期内月份,季度和半总销量(相应日期变量条件也需要事先定义,例如从包含在服务器GET请求中的查询参数)
Sales.aggregate()
.match(...include general non-date matches here, e.g. company, etc.)
.project({
'month': {
'$cond': { if: {
'$and': [
{ $gte: [ 'date', new Date(monthStartDate) ] },
{ $lte: [ 'date', new Date(monthEndDate) ] },
]}, then: 'amount', else: 0
}
},
'quarter': {
'$cond': { if: {
'$and': [
{ $gte: [ 'date', new Date(quarterStartDate) ] },
{ $lte: [ 'date', new Date(quarterEndDate) ] },
]}, then: 'amount', else: 0
}
},
'half': {
'$cond': { if: {
'$and': [
{ $gte: [ 'date', new Date(halfStartDate) ] },
{ $lte: [ 'date', new Date(halfEndDate) ] },
]}, then: 'amount', else: 0
}
}
})
.group({
_id: '_id',
month: { $sum: '$month' },
quarter: { $sum: '$quarter' },
half: { $sum: '$half' }
})
.exec(function(err, res) {
if (err) { reject(err) }
resolve(res)
})
谢谢,这已澄清了疑问。 –
感谢您提供聚合框架解决方案。 – tarashypka