एक अच्छा तरीका यह होगा कि प्रत्येक समूह यानी वार्षिक, मासिक और साप्ताहिक समुच्चय के साथ समुच्चय की गणना के उद्देश्य से कुल पाइपलाइन को कई चरणों में तोड़ दिया जाए।
मैंने उक्त पाइपलाइन को उत्पन्न करने का एक कमजोर प्रयास किया है, लेकिन यह सुनिश्चित नहीं है कि आप यही चाहते हैं, लेकिन आपको समाधान के लिए कुछ सुराग दे सकते हैं, बेहतर अभी तक एक इष्टतम। शायद कोई और बेहतर जवाब दे सकता है।
निम्नलिखित पर विचार करें अप्रयुक्त पाइपलाइन:
db.statements.aggregate([
{
"$group": {
"_id": {
"name": "$name",
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"week": { "$week": "$date" }
},
"total": { "$sum": "$amount" }
}
},
{
"$group": {
"_id": {
"name": "$_id.name",
"year": "$_id.year"
},
"YearlySpends": { "$push": "$total" },
"totalYearlyAmount": { "$sum": "$total" },
"data": { "$push": "$$ROOT" }
}
},
{ "$unwind": "$data" },
{
"$group": {
"_id": {
"name": "$_id.name",
"month": "$data._id.month"
},
"YearlySpends": { "$first": "$YearlySpends" },
"totalYearlyAmount": { "$first": "$totalYearlyAmount" },
"MonthlySpends": { "$push": "$data.total" },
"totalMonthlyAmount": { "$sum": "$data.total" },
"data": { "$push": "$data" }
}
},
{ "$unwind": "$data" },
{
"$group": {
"_id": {
"name": "$_id.name",
"week": "$data._id.week"
},
"YearlySpends": { "$first": "$YearlySpends" },
"totalYearlyAmount": { "$first": "$totalYearlyAmount" },
"MonthlySpends": { "$first": "$MonthlySpends" },
"totalMonthlyAmount": { "$first": "$totalMonthlyAmount" },
"WeeklySpends": { "$push": "$data.total" },
"totalWeeklyAmount": { "$sum": "$data.total" },
"data": { "$push": "$data" }
}
},
{ "$unwind": "$data" },
{
"$group": {
"_id": "$data._id",
"YearlySpends": { "$first": "$YearlySpends" },
"totalYearlyAmount": { "$first": "$totalYearlyAmount" },
"MonthlySpends": { "$first": "$MonthlySpends" },
"totalMonthlyAmount": { "$first": "$totalMonthlyAmount" },
"WeeklySpends": { "$first": "$WeeklySpends" },
"totalWeeklyAmount": { "$first": "$totalWeeklyAmount" }
}
}
])
नमूना आउटपुट
/* 1 */
{
"_id" : {
"name" : "Tesco",
"year" : 2017,
"month" : 3,
"week" : 11
},
"YearlySpends" : [
-3.3
],
"totalYearlyAmount" : -3.3,
"MonthlySpends" : [
-3.3
],
"totalMonthlyAmount" : -3.3,
"WeeklySpends" : [
-3.3
],
"totalWeeklyAmount" : -3.3
}
/* 2 */
{
"_id" : {
"name" : "RINGGO",
"year" : 2017,
"month" : 4,
"week" : 17
},
"YearlySpends" : [
-3.3,
-26.3,
-33.3
],
"totalYearlyAmount" : -62.9,
"MonthlySpends" : [
-33.3
],
"totalMonthlyAmount" : -33.3,
"WeeklySpends" : [
-33.3
],
"totalWeeklyAmount" : -33.3
}
/* 3 */
{
"_id" : {
"name" : "RINGGO",
"year" : 2017,
"month" : 3,
"week" : 12
},
"YearlySpends" : [
-3.3,
-26.3,
-33.3
],
"totalYearlyAmount" : -62.9,
"MonthlySpends" : [
-3.3,
-26.3
],
"totalMonthlyAmount" : -29.6,
"WeeklySpends" : [
-3.3
],
"totalWeeklyAmount" : -3.3
}
/* 4 */
{
"_id" : {
"name" : "RINGGO",
"year" : 2017,
"month" : 3,
"week" : 11
},
"YearlySpends" : [
-3.3,
-26.3,
-33.3
],
"totalYearlyAmount" : -62.9,
"MonthlySpends" : [
-3.3,
-26.3
],
"totalMonthlyAmount" : -29.6,
"WeeklySpends" : [
-26.3
],
"totalWeeklyAmount" : -26.3
}
/* 5 */
{
"_id" : {
"name" : "Sky",
"year" : 2017,
"month" : 3,
"week" : 9
},
"YearlySpends" : [
-63.3
],
"totalYearlyAmount" : -63.3,
"MonthlySpends" : [
-63.3
],
"totalMonthlyAmount" : -63.3,
"WeeklySpends" : [
-63.3
],
"totalWeeklyAmount" : -63.3
}
/* 6 */
{
"_id" : {
"name" : "Amazon",
"year" : 2017,
"month" : 3,
"week" : 12
},
"YearlySpends" : [
-61.3
],
"totalYearlyAmount" : -61.3,
"MonthlySpends" : [
-61.3
],
"totalMonthlyAmount" : -61.3,
"WeeklySpends" : [
-61.3
],
"totalWeeklyAmount" : -61.3
}
अपडेट करें
यदि आप समग्र संचालन में फ़िल्टर शामिल करना चाहते हैं तो मेरा सुझाव है कि आप $मैच
पहले पाइपलाइन चरण के रूप में क्वेरी। हालांकि, अगर कोई शुरुआती $मिलान
चरण तो पिछले चरणों को थोड़ा बदल दिया जाएगा क्योंकि आप फ़िल्टर किए गए परिणामों को एकत्रित करेंगे, शुरुआत में सभी दस्तावेज़ों को समग्र रूप से एकत्र करने और फिर परिणामों पर फ़िल्टर लागू करने से बहुत अलग।
अगर आपको फ़िल्टर-फर्स्ट-फिर-एग्रीगेट . लेना है मार्ग, एक समग्र संचालन चलाने पर विचार करें जो का उपयोग करता हो। $मिलान
पहले चरण के रूप में जो विक्रेता द्वारा दस्तावेज़ों को फ़िल्टर करता है, फिर एक पूर्ववर्ती $redact
दिनांक फ़ील्ड के महीने भाग पर दस्तावेज़ों को और फ़िल्टर करने के लिए पाइपलाइन चरण और फिर शेष $ग्रुप
चरण:
Statements.aggregate([
{ "$match": { "name": req.params.vendor } },
{
"$redact": {
"$cond": [
{ "$eq": [{ "$month": "$date" }, parseInt(req.params.month) ]},
"$$KEEP",
"$$PRUNE"
]
}
},
.....
/*
add the remaining pipeline steps after
*/
], function(err, data){
if (err) throw err;
console.log(data);
})
अगर आपको ग्रुप-फर्स्ट-फिर-फिल्टर . लेना है मार्ग, तो फ़िल्टर अंतिम पाइपलाइन के बाद होगा जो समूहीकृत परिणाम देता है लेकिन विभिन्न क्षेत्रों पर लागू होता है क्योंकि धारा के उस हिस्से के नीचे के दस्तावेज़ मूल स्कीमा से अलग होंगे।
यह मार्ग प्रदर्शनकारी नहीं है क्योंकि आप संग्रह में सभी दस्तावेज़ों के साथ समग्र संचालन शुरू कर रहे हैं और फिर बाद में फ़िल्टर कर रहे हैं:
Statements.aggregate([
.....
/*
place the initial pipeline steps from
the original query above here
*/
.....
{
"$match": {
"_id.name": req.params.vendor,
"_id.month": parseInt(req.params.month)
}
}
], function(err, data){
if (err) throw err;
console.log(data);
})
एकाधिक दिनांक फ़िल्टर पैरामीटर के लिए, $react
ऑपरेटर होगा
{
"$redact": {
"$cond": [
{
"$and": [
{ "$eq": [{ "$year": "$date" }, parseInt(req.params.year) ]},
{ "$eq": [{ "$month": "$date" }, parseInt(req.params.month) ]},
{ "$eq": [{ "$week": "$date" }, parseInt(req.params.week) ]}
]
},
"$$KEEP",
"$$PRUNE"
]
}
}