2016-01-22 8 views
5

पर समेकन द्वारा मैं mongodb 2.6 का उपयोग करता हूं। मैं इस रूप में अपने डेटा को संग्रहीत किया है:समूह MongoDb

{ 
    "_id" : "my-sensor-1", 
    "points": [ 
     { "timeStamp" : NumberLong("1453468362174"), "value" : 41 }, 
     { "timeStamp" : NumberLong("1453468483297"), "value" : 66 }, 
     { "timeStamp" : NumberLong("1453468485568"), "value" : 49 }, 
     ...  
    ] 
} 

आदेश दस्तावेजों मैं इस तरह के प्रश्नों बनाने के समेकित करने में:

db.pointsTest.aggregate([ 
    { $match: { $and: [ {"points.timeStamp" : { $gt : 1453433925163}}, 
         {"_id":"my-sensor-10"} ] } }, 
    {"$unwind":"$points"}, 
    {$group: {_id: "my-sensor-1","average":{$avg : "$points.value"}}} 
]) 

{ "_ id": "मेरी सेंसर -1 "," औसत ": 52}

परिणाम

मैंने टाइमस्टैम्प को मिलीसेकंड के रूप में संग्रहीत किया है, इसलिए हर बार जब मैं एक विशिष्ट समय अंतराल को एकत्र करना चाहता हूं तो मुझे टाइमस्टैम्प मान की सीमाएं बदलनी होंगी।

मैं समय अवधि पर एकत्रीकरण कैसे कर सकता हूं और परिणामों को अंतराल अंतराल से समूहित कर सकता हूं (यानी अब से औसत मूल्य को एकत्रित करें() -1day ग्रुप 1h)?

संपादित

मैं कुछ इस तरह बनाना चाहते:

db.pointsTest.aggregate([ 
    { $match: { $and: [ {"points.timeStamp" : { $gt : 1453433925163, $lt : 1453555555555}}, {"_id":"my-sensor-10"} ] } }, {"$unwind":"$points"}, {$group: {_id: "my-sensor-1","average":{$avg : "$points.value"}, ???}} 
]) 

और परिणाम इस बार 1 घंटे के आधार पर वर्गीकृत अंतराल की औसत होगा। यह मानते हुए कि मैं दिसंबर के 31 के हर घंटे के लिए औसत मान इकट्ठा करना चाहते हैं:

अंतराल 31/12/2015 20:00:00, औसत के टाइमस्टैम्प: अंतराल 31 की xyz

टाइमस्टैम्प क्रम में प्राप्त करने के लिए मैं 1hour अंतराल में समय अंतराल विभाजित है और डेटाबेस के लिए कई अनुरोध करने के लिए है कि xyz

इस समय:/12/2015 21:00:00, औसत।

आईई InfluxDB का उपयोग कर एक ही मैं यह करने के करने के लिए:

"SELECT MEAN(value) From myMeasures where key='my-sensor-1' and time > now() - 1d GROUP BY time(1h)" 

उत्तर

1

आपको विभिन्न अंतराल के आधार पर डेटा समूह करने के लिए मोंगो क्वेरी में कुछ गणितीय गणना करने की आवश्यकता है।

$ घटाना और $ mod का संयोजन आपको विशिष्ट अंतराल में डेटा समूहित करने में मदद करेगा।

क्वेरी निम्नलिखित तरह होगा:

db.sensor.aggregate({ 
    $match: { 
    $and: [{ 
     "points.timeStamp": { 
      $gt: 1453433925163, 
      $lt: 1453555555555 
     } 
    }, { 
     "_id": "my-sensor-1" 
    }] 
    } 
}, { 
    $unwind: "$points" 
}, { 
    "$group": { 
    "_id": { 
     "$subtract": ["$points.timeStamp", { 
      "$mod": ["$points.timeStamp", 1000 * 60] 
     }] 
    }, 
    "average": { 
     "$avg": "$points.value" 
    } 
    } 
}) 

आशा, यह आपके लिए उपयोगी होगा।

+0

वास्तव में उपयोगी है लेकिन मैं यह कुछ याद आ रही है लगता है (शायद मैं अपने प्रश्न पर यह निर्दिष्ट नहीं किया है)। सूची में वस्तुओं को फिर से शुरू करने के लिए मुझे एक और $ मैच जोड़ना पड़ा क्योंकि जब स्थिति सही होती है तो यह पूरे आइटम लौटाती है। तो क्वेरी इस तरह है: db.pointsTest.aggregate ({$ match: {$ और: [{"points.timeStamp": {$ gte: 1453797806927}}, {"_id": "my-sensor-1"} ]}}, {$ unwind: "$ points"}, {$ match: {"points.timeStamp": {$ gte: 1453797806927}}}, {"$ समूह": {"_id": {"$ घटाएं" : ["$ अंक। टाइमस्टैम्प", {"$ mod": ["$ points.timeStamp", 1000 * 60]}]}, "औसत": {"$ avg": "$ points.value"}}}) – bill

1

अंतराल के अंतराल में परिणाम प्राप्त करने के लिए, आपके द्वारा अपनी क्वेरी का समर्थन करने के जावास्क्रिप्ट कार्यों का उपयोग कर सकते हैं के बाद से MongoDB खोल उन्हें समर्थन करता है:

उदाहरण के साथ उदाहरण निष्पादित करने के लिए आपके द्वारा दी गई है, जहां आप now()-1day से $match मूल्यों करना चाहते हैं, तो आप अपने एकत्रीकरण से पहले ऐसा कर सकते हैं:

var now = new Date(); 
var yesterday = new Date(); 
// using getHours and setHours, since the Date object doesnt have method for getDays and setDays 
yesterday.setHours(now.getHours() - 24); 

yesterday.getTime() Milis में तारीख निकलेगा, जो आप $match चरण

db.pointsTest.aggregate([ 
    { $match: { $and: [ {"points.timeStamp" : { $gt : yesterday.getTime()}}, 
         {"_id":"my-sensor-10"} ] } }, 

अब घंटे के अंतराल में समूह के परिणाम के लिए अपने एकत्रीकरण में उपयोग कर सकते हैं, मैं जोड़ने के लिए $group से पहले एक $project चरण जोड़ना होगा, एक नया क्षेत्र, जहां प्रति घंटा अंतराल की गणना की जाती है, points.timeStamp - yesterday.getTime() के साथ आपको प्रारंभिक समय और प्रवेश समय के बीच मिलीसेकंड की कुल दुविधा मिल जाएगी, आप इसे घंटों तक बदलते हैं और अगले पूर्णांक मान तक ले जाते हैं।

और अंत में चरण से उस नए फ़ील्ड का उपयोग करें, जिसका उपयोग $group चरण में किया जाना है।

1

आप आसानी से इसे mongodb mapReduce के साथ कर सकते हैं।

निम्नलिखित कोड का प्रयास करें:

// generate a query to filter result by date and _id. 
// be aware that our query matches documents that contain an array field with 
// at least one element that matches all the specified criteria. 
var yesterday = new Date(); 
yesterday.setDate(yesterday.getDate()-1); 
var query = {"points.timeStamp" : { $gt : yesterday.getTime()}, "_id":"my-sensor-1"}; 

var map = function(){ 
    var points = this.points; 
    for(var i=0;i<points.length;i++){ 
     var date = new Date(points[i].timeStamp); 

     //remove minutes, seconds and milliseconds from the date and emit it 
     date.setHours(date.getHours(), 0, 0, 0); 
     emit(date, points[i].value); 
    } 
}; 

var reduce = function(key, values){ 
    //calculate average 
    var total = 0; 
    for(var i = 0; i < values.length; i++) { 
     total += values[i]; 
    } 
    var avg = total/values.length; 
    return avg; 
}; 

db.pointsTest.mapReduce(map, reduce, {out:{inline: 1}, query: query})