सीधे अपने प्रश्न का उत्तर देने के लिए, हाँ यह सबसे प्रभावी तरीका है। लेकिन मुझे लगता है कि हमें यह स्पष्ट करने की जरूरत है कि ऐसा क्यों है।
के रूप में विकल्प में सुझाव दिया गया था, एक बात लोगों को है एक $group
मंच और वे क्या, "टाइमस्टैम्प" मूल्य है पर देख रहे हैं तो आप बनाना चाहते हैं के लिए पार करने से पहले अपने परिणामों को "छँटाई" देख रहे हैं सुनिश्चित करें कि सब कुछ, "टाइमस्टैम्प" क्रम में है तो इसलिए प्रपत्र:
db.temperature.aggregate([
{ "$sort": { "station": 1, "dt": -1 } },
{ "$group": {
"_id": "$station",
"result": { "$first":"$dt"}, "t": {"$first":"$t"}
}}
])
और जैसा कि कहा गया है कि आप निश्चित रूप से एक सूचकांक को प्रतिबिंबित करने के इसी क्रम तरह कुशल बनाने के लिए में चाहते हैं:
हालांकि , और थाई एस असली बिंदु है।ऐसा लगता है कि दूसरों द्वारा अनदेखा किया गया है (यदि आपके लिए ऐसा नहीं है) यह है कि इस डेटा के सभी समय पहले से डालने की संभावना है, जिसमें प्रत्येक पाठ को जोड़ा गया है।
तो यह की सुंदरता _id
क्षेत्र (एक डिफ़ॉल्ट ObjectId
के साथ) "टाइमस्टैम्प" क्रम में पहले से ही है, के रूप में यह अपने आप करता है वास्तव में एक समय मान है और इस बयान को संभव बनाता है:
db.temperature.aggregate([
{ "$group": {
"_id": "$station",
"result": { "$last":"$dt"}, "t": {"$last":"$t"}
}}
])
और यह तेज है। क्यूं कर? खैर आपको एक इंडेक्स (आमंत्रित करने के लिए अतिरिक्त कोड) चुनने की आवश्यकता नहीं है, आपको दस्तावेज़ के अतिरिक्त इंडेक्स को "लोड" करने की आवश्यकता नहीं है।
हम पहले से ही जानते हैं कि दस्तावेजों के क्रम में (_id
द्वारा) कर रहे हैं तो $last
सीमाओं पूरी तरह से वैध है। आप वैसे भी सबकुछ स्कैन कर रहे हैं, और आप _id
मानों पर भी "रेंज" क्वेरी को दो तिथियों के बीच समान रूप से वैध मान सकते हैं।
यहाँ कहने के लिए केवल असली बात यह है कि "वास्तविक दुनिया" में उपयोग, यह सिर्फ आप के लिए और अधिक व्यावहारिक $match
तिथियों की सीमाओं के रूप में हो रही है "पहले करने का विरोध किया जब संचय की इस तरह कर रही है के बीच करने के लिए हो सकता है "और" अंतिम "_id
मान" वास्तविक "या आपके वास्तविक उपयोग में समान कुछ परिभाषित करने के लिए मान।
तो इसका सबूत कहां है? खैर यह पुन: पेश करने में काफी आसान है, तो मैं बस कुछ नमूना डेटा उत्पन्न करके वैसा ही किया: (Spinny डिस्क, जो तारकीय नहीं है, लेकिन निश्चित रूप से पर्याप्त के साथ 8 जीबी लैपटॉप) मेरी हार्डवेयर पर
var stations = [
"AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL",
"GA", "HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA",
"ME", "MD", "MA", "MI", "MN", "MS", "MO", "MT", "NE",
"NV", "NH", "NJ", "NM", "NY", "NC", "ND", "OH", "OK",
"OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VT",
"VA", "WA", "WV", "WI", "WY"
];
for (i=0; i<200000; i++) {
var station = stations[Math.floor(Math.random()*stations.length)];
var t = Math.floor(Math.random() * (96 - 50 + 1)) +50;
dt = new Date();
db.temperatures.insert({
station: station,
t: t,
dt: dt
});
}
के प्रत्येक फार्म चल रहे कथन स्पष्ट रूप से एक इंडेक्स और एक प्रकार का उपयोग कर संस्करण के साथ एक उल्लेखनीय विराम दिखाता है (सॉर्ट स्टेटमेंट के रूप में इंडेक्स पर एक ही कुंजी)। यह केवल मामूली विराम है, लेकिन अंतर ध्यान देने के लिए पर्याप्त महत्वपूर्ण है।
भी समझाने उत्पादन को देखकर (संस्करण 2.6 और ऊपर, या वास्तव में 2.4.9 हालांकि दस्तावेज नहीं में है) आपको लगता है कि में अंतर देख सकते हैं, हालांकि $sort
एक की उपस्थिति के कारण बाहर अनुकूलित है सूचकांक, लिया गया समय इंडेक्स चयन के साथ होता है और फिर अनुक्रमित प्रविष्टियों को लोड करता है। "कवर" अनुक्रमणिका क्वेरी के लिए सभी फ़ील्ड सहित कोई फर्क नहीं पड़ता।
रिकॉर्ड के लिए, तारीख को पूरी तरह से अनुक्रमणित करना और तारीख मानों पर केवल क्रमबद्ध करना एक ही परिणाम देता है। शायद थोड़ा तेज, लेकिन बिना किसी प्रकार के प्राकृतिक सूचकांक रूप से धीमा।
तो जब तक आप खुशी से पहले और पिछले_id
मूल्यों पर "सीमा" के रूप में है, तो यह सच है कि प्रविष्टि के आदेश पर प्राकृतिक सूचकांक का उपयोग कर वास्तव में यह करने के लिए सबसे कारगर तरीका है। आपका वास्तविक विश्व लाभ इस बात पर भिन्न हो सकता है कि यह आपके लिए व्यावहारिक है या नहीं और यह सूचकांक को लागू करने और तिथि को क्रमबद्ध करने के लिए अधिक सुविधाजनक हो सकता है।
लेकिन अगर आप अपनी क्वेरी में _id
श्रेणियों या "अंतिम" _id
से अधिक से अधिक खुश हैं, तो शायद आपके परिणामों के साथ मूल्य प्राप्त करने के लिए एक ट्विक करें ताकि आप वास्तव में उस जानकारी को स्टोर और उपयोग कर सकें लगातार प्रश्नों:
db.temperature.aggregate([
// Get documents "greater than" the "highest" _id value found last time
{ "$match": {
"_id": { "$gt": ObjectId("536076603e70a99790b7845d") }
}},
// Do the grouping with addition of the returned field
{ "$group": {
"_id": "$station",
"result": { "$last":"$dt"},
"t": {"$last":"$t"},
"lastDoc": { "$last": "$_id" }
}}
])
और अगर आप वास्तव में "पर निम्नलिखित" कर रहे थे कि जैसे परिणाम तो आप अपने परिणामों से ObjectId
की अधिकतम मूल्य निर्धारित और अगले क्वेरी में इसका इस्तेमाल कर सकते हैं।
किसी भी तरह, इसके साथ मज़े करना मज़ेदार है, लेकिन फिर हां, इस मामले में यह प्रश्न सबसे तेज़ तरीका है।
आपके द्वारा निललुन से स्वीकार किए गए उत्तर वास्तव में गलत हैं। प्राकृतिक आदेश को सम्मिलन आदेश (कैप्ड संग्रहों को छोड़कर) होने की गारंटी नहीं है और _id केवल आपके क्लाइंट मशीनों के सभी * समय सिंक्रनाइज़ होने पर एकान्त रूप से बढ़ने की गारंटी है। –