2014-06-19 9 views
5

मैं डेटा के कुल सेट के लिए mongodb एकत्रीकरण का उपयोग कर रहा हूं। मेरी स्थिति थोड़ा जटिल है। मैं निम्नलिखित के रूप में एक संग्रह है:दिन के बाद मोंगोडब एकत्रीकरण

{ 
    startTime: ISODate("2014-12-31T10:20:30Z"), 
    customerId: 123, 
    ping: "2", 
    link: "3" 
} 

अब मैं निम्नलिखित के रूप में एक और संग्रह करने के लिए डेटा इकट्ठा करना चाहते हैं:

{ 
_id: { 
day: ISODate("2014-12-31T00:00:00Z"), 
customerId: 123 
}, 
hours: [ 
    { 
    hour: ISODate("2014-12-31T10:00:00Z"), 
    pings: 2, 
    links: 3 
    }, 
    { 
    hour: ISODate("2014-12-31T11:00:00Z"), 
    pings: 5, 
    links: 6 
    } 
] 
} 

आप देख सकते हैं डेटा घंटे से पहले और उसके बाद दिन-ब-समूह है। मुझे दिन भर उन्हें समूहबद्ध करने के लिए निम्नलिखित समेकन क्वेरी मिल गई है लेकिन घंटों तक उन्हें कैसे समूहित किया जाए? कोई उपाय?

var pipeline = [ 
{ 
$project : { 
     startTime : 1, 
       customerId: 1, 
     ping:1, 
     link:1, 
     date : "$startTime", 
     h : { 
      "$hour" : "$startTime" 
     }, 
     m : { 
      "$minute" : "$startTime" 
     }, 
     s : { 
      "$second" : "$startTime" 
     }, 
     ml : { 
      "$millisecond" : "$startTime" 
     } 
    } 
}, 
{ 
$project: { 
    startTime : 1, 
      customerId: 1, 
    ping:1, 
    link:1, 
     date : {  
      "$subtract" : [  
       "$date",  
       {  
         "$add" : [  
          "$ml",  
          {  
           "$multiply" : [  
            "$s",  
            1000  
           ]  
          },  
          {  
           "$multiply" : [  
            "$m",  
            60,  
            1000  
           ]  
          }, 
          {  
           "$multiply" : [  
            "$h",  
            60,  
            60,  
            1000 
           ]  
          }  
         ]  
       }  
      ]  
     } 
    }   
}, 
{ 
    $match: { 
     "startTime": { 
      $gte: new ISODate("2013-12-01T07:00:00Z"), 
      $lte: new ISODate("2014-01-01T08:00:00Z"), 
     } 
    } 
}, 
// Aggregate the data 
{ 
    $group: { 
     _id: {day : "$date", customerId: "$customerId"}, 
     pings : {$sum: "$ping"}, 
     links : {$sum: "$links"} 
    } 
} 
]; 

उत्तर

7

क्या आप मूल रूप से चाहते हैं एक डबल समूहीकरण है, लेकिन आप वापस date aggregation operators सिर्फ प्रासंगिक भागों का उपयोग कर, पूरे तारीख वस्तु नहीं मिलता:

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 
      } 
    ] 
} 

आप मुश्किल करने के लिए तिथि ऑपरेटरों के साथ सौदा या तिथि वस्तुओं के लिए एक सरल "पास-थ्रू" परिणाम चाहते हैं के परिणाम प्राप्त होते हैं, तो युग के बजाय timestamps के रूप में आप डाली सकता है: है

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 ऑपरेटर आप scoped के संचालन के लिए "चर" की घोषणा की अनुमति देता है कि के माध्यम से जोड़ सकते हैं:

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

इसके अलावा, मैं लगभग कि उल्लेख करना भूल गया "पिंग के लिए अपने मूल्यों "और" लिंक "वास्तव में स्ट्रिंग्स हैं जब तक कि यह एक टाइपो नहीं है। लेकिन यदि नहीं, तो सुनिश्चित करें कि आप उन्हें पहले नंबर के रूप में परिवर्तित करें।

+0

धन्यवाद। क्या आप कृपया मेरी मदद कर सकते हैं? मेरे पास एक शेड्यूलर है जो पिछले घंटे से डेटा को पिछले घंटे से एकत्र करने के लिए हर घंटे चलाएगा: '{" _id ": { " ग्राहक आईडी ": 123," दिन ": ISODate (" 2012-06-20: 00: 00 : 00Z ")}, " घंटे ": [{" घंटा ": ISODate (" 2012-06-20: 01: 00: 00Z ")," पिंग्स ": 2," लिंक ": 3}]} 'के बाद उपरोक्त समेकन क्वेरी चलाते हुए, मुझे एकत्रित डेटा को संग्रहीत करने के लिए इस संग्रह में विलय/अपरिवर्तित करने की आवश्यकता है। मैं उसे कैसे प्राप्त कर सकता हूं? धन्यवाद – user3756522

+0

@ user3756522 यह वास्तव में एक और प्रश्न की तरह लगता है और सबसे अच्छी तरह से एक नई पोस्ट के रूप में पूछा जाता है जहां आप टिप्पणियों के बजाए अपना इरादा ठीक से समझाते हैं। उत्तर में दिखाए गए प्रश्न को आपके द्वारा भेजे जाने वाले सीमा के लिए हर दिन और हर घंटे एकत्रित किया जाएगा। इसके लिए आपका '$ मैच' हमेशा पाइपलाइन का ** पहला ** चरण होना चाहिए। MongoDB 2.6 के साथ आपका कुल आउटपुट एक कर्सर हो सकता है जिसे आप परिणामों को संसाधित करने के लिए पुन: प्रयास करते हैं –

संबंधित मुद्दे