2016-07-31 47 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

相關問題