2016-07-31 48 views

回答

0

您可以使用aggregation framework做到这一点,如果map-reduce能够解决您手头的问题,那么它是首选,因为它通常都是可读的,速度更快。

当然,如何这条管道的样子取决于你的文档的形状(我还不知道),但计算一次所有三个总和应尽可能用$match阶段过滤下来的文件和$group阶段做总和计算。
$group阶段中,您可以使用$sum运算符与嵌套$cond运算符有条件地总结月份,季度和半年的值。

0

假设你有一个销售收取的是单据,

{ "_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 } 

应进一步根据任务本地处理。

2

根据文档字段的具体情况,可以通过汇总框架,使用match,projectgroup阶段的组合完成此操作。

举个例子,我将承担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) 
}) 
+0

谢谢,这已澄清了疑问。 –

+0

感谢您提供聚合框架解决方案。 – tarashypka

相关问题