अगर यह केवल 10 सेकंड के अंतराल के भीतर चीजों को प्राप्त करने के बारे में है, तो आप थोड़ा गणित कर सकते हैं और इसे कुल मिलाकर चला सकते हैं:
db.collection.aggregate([
{ "$group": {
"_id": {
"year": { "$year": "$created_at" },
"month":{ "$month": "$created_at" },
"day": { "$dayOfMonth": "$created_at" },
"hour": { "$hour": "$created_at" },
"minute": { "$minute": "$created_at" },
"second": { "$subtract": [
{ "$second": "$created_at" },
{ "$mod": [
{ "$second": "$created_at" },
10
]}
]}
},
"count": { "$sum" : 1 }
}}
])
ताकि चीजें एक मिनट में 10 सेकंड के अंतराल तक टूट जाएं जहां वे थोड़े से मॉड 10 गणित के साथ घटित हों।
मुझे लगता है कि यह उचित है, और यह सबसे तेज़ धावक होगा क्योंकि यह कुल का उपयोग करता है। यदि आपको वास्तव में अपने अनुक्रम की आवश्यकता है जैसा कि शुरू में मिलान किए गए समय से 10 सेकंड चलने के लिए दिखाया गया है, तो आप इस प्रक्रिया को mapReduce के साथ कर सकते हैं:
पहले एक मैपर:
var mapper = function () {
if ( this.created_at.getTime() > ( last_date + 10000 ) ) {
if ( last_date == 0 ) {
last_date = this.created_at.getTime();
} else {
last_date += 10000;
}
}
emit(
{
start: new Date( last_date ),
end: new Date( last_date + 10000 )
},
this.created_at
);
}
तो यह 10 सेकंड के अंतराल के भीतर तारीखों का उत्सर्जन करने जा रहा है, पहली तारीख से शुरू होकर और फिर हर बार अंतराल को बढ़ाता है जब कुछ सीमा से बाहर पाया जाता है
अब आपको एक रिड्यूसर चाहिए:
var reducer = function (key, values) {
return values.length;
};
बहुत आसान। बस पास की गई सरणी की लंबाई लौटाएं।
क्योंकि mapReduce जिस तरह से काम करता है, वह कुछ भी जिसमें एक से अधिक मान नहीं होते हैं, उसे रिड्यूसर को पास नहीं किया जाता है, इसलिए इसे अंतिम रूप देकर साफ करें:
var finalize = function (key, value) {
if ( typeof(value) == "object" ) {
value = 1;
}
return value;
};
फिर परिणाम प्राप्त करने के लिए इसे चलाएं। "स्कोप" अनुभाग पर ध्यान दें जो मैपर में उपयोग किए जाने वाले वैश्विक चर को पास करता है:
db.collection.mapReduce(
mapper,
reducer,
{
"out": { "inline": 1 },
"scope": { "last_date": 0 },
"finalize": finalize
}
)
प्रत्येक दृष्टिकोण थोड़ा अलग परिणाम देने की संभावना है, लेकिन यह बात है। यह इस बात पर निर्भर करता है कि आप वास्तव में किसका उपयोग करना चाहते हैं।
आपकी टिप्पणी को ध्यान में रखते हुए आप या तो किसी भी कथन से आउटपुट का "निरीक्षण" कर सकते हैं और प्रोग्रामिक रूप से "अंतराल भरें"। मैं आम तौर पर उस विकल्प को पसंद करता हूं, लेकिन यह मेरा कार्यक्रम नहीं है और मुझे नहीं पता कि आप इस क्वेरी से कितनी बड़ी श्रृंखला प्राप्त करने का प्रयास कर रहे हैं।
सर्वर साइड पर, आप कुछ ऐसा करने के लिए "मैपर" को पैच अप कर सकते हैं:
var mapper = function () {
if ( this.created_at.getTime() > ( last_date + 10000 ) ) {
if ( last_date == 0 ) {
last_date = this.created_at.getTime();
} else {
// Patching for empty blocks
var times = Math.floor(
( this.created_at.getTime() - last_date ) / 10000
);
if ( times > 1 ) {
for ( var i=1; i < times; i++ ) {
last_date += 10000;
emit(
{
start: new Date( last_date ),
end: new Date( last_date + 10000 )
},
0
);
}
}
// End patch
last_date += 10000;
}
}
emit(
{
start: new Date( last_date ),
end: new Date( last_date + 10000 )
},
this.created_at
);
}