2016-07-31 4 views
2

Es ist möglich, in einer Abfrageaggregation die Summe der Verkäufe für den Monat, das Viertel und die Hälfte zu erhalten, oder ich mache jede Abfrage separat?Es ist möglich, in einer Menge Abfrage Umsatz für den Monat, Quartal und Semester Mongodb zu erhalten?

Egal, das Modell, meine Frage ist, ob Sie alle Informationen in einer einzigen Abfrage erhalten können oder sollte ich es separat tun.

Wenn nicht, was wäre der beste Weg, um diese Informationen zu erhalten?

Antwort

0

Sie können dies mit der aggregation framework tun, die im Vergleich zu map-reduce bevorzugt wird, wenn es in der Lage ist, Ihr Problem auf der Hand zu lösen, da es meistens sowohl lesbarer als auch schneller ist.

Natürlich, wie diese Pipeline aussieht hängt von der Form Ihrer Dokumente ab (was ich noch nicht weiß) aber die Berechnung aller drei Summen auf einmal sollte möglich sein mit einer $match Bühne hinunter die Dokumente und eine $group Bühne tun die Summenberechnungen.
In der Stufe $group können Sie dann den Operator $sum mit den verschachtelten Operatoren $cond verwenden, um die Werte für den Monat, das Quartal und das halbe Jahr bedingt zu summieren.

0

Vorausgesetzt Sie haben eine Verkaufssammlung mit Dokumenten

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

Mit Karten reduzieren die Lösung

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 } }); 

Die Ergebnisse sind

"results" : [ { "_id" : "lastSemester", "value" : 210 }, 
       { "_id" : "lastMonth", "value" : 40 }, 
       { "_id" : "lastQuarter", "value" : 100 } ] 

Obwohl

sein, ich weiß nicht (und möchte) wissen, wie man es mit Aggregation für diese bestimmte Sammlung erreichen kann.

Das einzige, was, was in den Sinn kommt, ist zu $group Monat

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" ] } } } }); 

, die die Ergebnisse

{ "_id" : 11, "totalPrice" : 40 } 
{ "_id" : 9, "totalPrice" : 60 } 
{ "_id" : 8, "totalPrice" : 20 } 
{ "_id" : 7, "totalPrice" : 60 } 
{ "_id" : 6, "totalPrice" : 30 } 

gibt, die lokal weiter verarbeitet werden soll, entsprechend der Aufgabe.

2

Je nach den Besonderheiten Ihrer Dokumentfelder, kann dies über die Aggregation Rahmen durchgeführt werden, eine Kombination aus match, project und group Stufen verwenden.

Als Beispiel werde mir ein Sales Dokument, mit date Feld und ein amount Feld zu übernehmen, die aggregiert werden soll den Gesamtumsatz für einen bestimmten Zeitraum (die jeweiligen Datumsvariablen für den Monat, Quartal und die Hälfte zu bekommen Konditionale müssten auch vorher definiert werden, zB aus den Abfrageparametern, die in einer Server-GET-Anfrage enthalten sind)

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

Danke, das hat den Zweifel geklärt. –

+0

Danke für die Bereitstellung von Aggregation-Framework-Lösung. – tarashypka

Verwandte Themen