आप मूल रूप से एक दोहरा समूह बनाना चाहते हैं, लेकिन आपको तारीख एग्रीगेशन ऑपरेटर्स , केवल प्रासंगिक भाग:
db.collection.aggregate([
{ "$group": {
"_id": {
"customerId": "$customerId",
"day": { "$dayOfYear": "$startTime" },
"hour": { "$hour": "$startTime" }
},
"pings": { "$sum": "$ping" },
"links": { "$sum": "$link" }
}},
{ "$group": {
"_id": {
"customerId": "$_id.customerId",
"day": "$_id.day"
},
"hours": {
"$push": {
"hour": "$_id.hour",
"pings": "$pings",
"links": "$links"
}
}
}}
])
डबल $group
प्रति दिन एक सरणी में परिणाम रखकर आपको वह प्रारूप देता है जो आप चाहते हैं। नमूने में एकल दस्तावेज़, लेकिन आपको मूल रूप से इस तरह के परिणाम मिलते हैं:
{
"_id" : {
"customerId" : 123,
"day" : 365
},
"hours" : [
{
"hour" : 10,
"pings" : 2,
"links" : 3
}
]
}
यदि आपको दिनांक ऑपरेटरों के परिणामों से निपटना मुश्किल लगता है या दिनांक ऑब्जेक्ट के लिए एक सरल "पास-थ्रू" परिणाम चाहते हैं, तो आप इसके बजाय युग टाइमस्टैम्प के रूप में कास्ट कर सकते हैं:
db.collection.aggregate([
{ "$group": {
"_id": {
"customerId": "$customerId",
"day": {
"$subtract": [
{ "$subtract": [ "$startTime", new Date("1970-01-01") ] },
{
"$mod": [
{ "$subtract": [ "$startTime", new Date("1970-01-01") ] },
1000*60*60*24
]
}
]
},
"hour": {
"$subtract": [
{ "$subtract": [ "$startTime", new Date("1970-01-01") ] },
{
"$mod": [
{ "$subtract": [ "$startTime", new Date("1970-01-01") ] },
1000*60*60
]
}
]
}
},
"pings": { "$sum": "$ping" },
"links": { "$sum": "$link" }
}},
{ "$group": {
"_id": {
"customerId": "$_id.customerId",
"day": "$_id.day"
},
"hours": {
"$push": {
"hour": "$_id.hour",
"pings": "$pings",
"links": "$links"
}
}
}}
])
जब आप $subtract
एक तिथि वस्तु दूसरे से आपको परिणामस्वरूप "युग" मान वापस मिल जाता है। इस मामले में हम संपूर्ण टाइमस्टैम्प मान प्राप्त करने के लिए "युग" प्रारंभ तिथि का उपयोग करते हैं और आवश्यक अंतराल के समय को सही करने के लिए केवल "तिथि गणित" प्रदान करते हैं। तो परिणाम:
{
"_id" : {
"customerId" : 123,
"day" : NumberLong("1419984000000")
},
"hours" : [
{
"hour" : NumberLong("1420020000000"),
"pings" : 2,
"links" : 3
}
]
}
आपकी आवश्यकताओं के आधार पर परिणाम के रूप में ऑपरेटर द्वारा प्रदान की जाने वाली तारीख से जो आपके लिए अधिक स्वादिष्ट हो सकता है।
आप इसके लिए MongoDB 2.6 के साथ $let ऑपरेटर जो आपको स्कोप्ड ऑपरेशंस के लिए "वैरिएबल" घोषित करने की अनुमति देता है:
db.event.aggregate([
{ "$group": {
"_id": {
"$let": {
"vars": {
"date": { "$subtract": [ "$startTime", new Date("1970-01-01") ] },
"day": 1000*60*60*24,
"hour": 1000*60*60
},
"in": {
"customerId": "$customerId",
"day": {
"$subtract": [
"$$date",
{ "$mod": [ "$$date", "$$day" ] }
]
},
"hour": {
"$subtract": [
"$$date",
{ "$mod": [ "$$date", "$$hour" ] }
]
}
}
}
},
"pings": { "$sum": "$ping" },
"links": { "$sum": "$link" }
}},
{ "$group": {
"_id": {
"customerId": "$_id.customerId",
"day": "$_id.day"
},
"hours": {
"$push": {
"hour": "$_id.hour",
"pings": "$pings",
"links": "$links"
}
}
}}
])
इसके अलावा, मैं लगभग यह उल्लेख करना भूल गया कि "पिंग" और "लिंक" के लिए आपके मूल्य वास्तव में तार हैं जब तक कि यह एक टाइपो न हो। लेकिन यदि नहीं, तो सुनिश्चित करें कि आप पहले उन्हें संख्याओं के रूप में परिवर्तित कर लें।