2009-07-09 9 views
9

मैं एक जीक्यूएल क्वेरी लिखने की कोशिश कर रहा हूं जो एक विशिष्ट प्रकार के एन यादृच्छिक रिकॉर्ड देता है। मेरा वर्तमान कार्यान्वयन काम करता है लेकिन डेटास्टोर को एन कॉल की आवश्यकता होती है। यदि संभव हो तो मैं डेटास्टोर को 1 कॉल करना चाहता हूं।एपेंगिन डेटास्टोर पर एन यादृच्छिक अभिलेखों के लिए पूछताछ

मैं वर्तमान में डेटास्टोर में रखे गए हर प्रकार के लिए एक यादृच्छिक संख्या असाइन करता हूं। जब मैं एक यादृच्छिक रिकॉर्ड के लिए पूछता हूं तो मैं रिकॉर्ड्स के लिए एक और यादृच्छिक संख्या और क्वेरी उत्पन्न करता हूं> रैंड ऑर्डर द्वारा आरोही LIMIT 1.

यह काम करता है, हालांकि, यह केवल 1 रिकॉर्ड देता है इसलिए मुझे एन प्रश्न करने की आवश्यकता है। इस सवाल को कैसे बनाया जाए इस पर कोई विचार? धन्यवाद।

+0

मैं इस के लिए एक मुद्दा बना लिया है, आप मदद करने के लिए यह तय मिल इसे तारांकित कर सकते हैं: https://code.google.com/p/googleappengine/issues/detail?id=9044 –

उत्तर

5

"हुड के तहत" एक एकल खोज क्वेरी कॉल केवल कुछ इंडेक्स से लगातार पंक्तियों का एक सेट लौटा सकती है। यही कारण है कि कुछ जीक्यूएल प्रश्न, जिनमें किसी भी प्रयोग शामिल हैं! =, एकाधिक डेटास्टोर कॉल में विस्तारित है।

एन स्वतंत्र वर्दी यादृच्छिक चयन किसी भी सूचकांक में लगातार (सामान्य रूप से) नहीं होते हैं।

QED।

आप शायद इकाइयों को स्टोर करने के लिए memcache का उपयोग कर सकते हैं, और उनमें से एन को पकड़ने की लागत को कम कर सकते हैं। या यदि आपको इंडेक्स में "यादृच्छिक" चयन एक साथ बंद नहीं होने पर कोई फर्क नहीं पड़ता है, तो एक क्वेरी में यादृच्छिक रूप से चुने गए ब्लॉक (कहें) 100 का चयन करें, फिर उनसे यादृच्छिक रूप से एन चुनें। चूंकि आपके पास ऐसा क्षेत्र है जो पहले ही यादृच्छिक है, यह बाहरी व्यक्ति के लिए तत्काल स्पष्ट नहीं होगा कि एन आइटम संबंधित हैं। कम से कम, जब तक वे बहुत सारे नमूने नहीं देखते हैं और ध्यान देते हैं कि आइटम ए और जेड एक ही समूह में कभी नहीं दिखाई देते हैं, क्योंकि वे यादृच्छिक अनुक्रमणिका में 100 से अधिक अलग हैं। और यदि प्रदर्शन परमिट होता है, तो आप समय-समय पर अपनी संस्थाओं को फिर से यादृच्छिक बना सकते हैं।

+0

धन्यवाद - मुझे वास्तव में यादृच्छिक परिणामों की आवश्यकता है इसलिए मुझे लगता है कि मुझे एकाधिक डेटास्टोर कॉल का उपयोग करना होगा। मैं उतना ही कम करने की कोशिश करूंगा जितना मैं अनुमान लगा सकता हूं। – aloo

+0

यह सच नहीं है। दोनों [बैच ऑपरेशंस] (https://developers.google.com/appengine/docs/python/datastore/entities?hl=hi#Batch_Operations) और ['IN'] (https://developers.google.com/ एपेंगिन/डॉक्स/पायथन/डेटास्टोर/प्रश्न # Property_Filters) क्वेरी ऑपरेटर निरंतर संस्थाओं को वापस कर सकता है। – ryan

+0

@ryan: '! =' के साथ ही। दोनों और 'IN' को सीमित संख्या में उप-प्रश्नों के रूप में लागू किया गया है। बैच ऑप्स प्रश्न के लिए वास्तव में प्रासंगिक नहीं हैं, लेकिन हां, यह सच है कि कुछ संचालन उन संस्थाओं पर कार्य करते हैं जो किसी भी सूचकांक में संगत नहीं हैं। बस खोज नहीं –

3

ऐसा लगता है कि एकमात्र विधि प्रत्येक इकाई की विशेष संपत्ति में यादृच्छिक पूर्णांक मान संग्रहीत करके और उस पर पूछताछ कर रही है। यदि आप स्वचालित रूप से स्वचालित रूप से प्रारंभिक संपत्ति जोड़ते हैं तो यह स्वचालित रूप से किया जा सकता है। यदि आपका डेटासंग्रह पहले से ही भरा है

दुर्भाग्य से यह एक बार सभी संस्थाओं के प्रसंस्करण की आवश्यकता होगी।

यह अजीब है, मुझे पता है।

+0

मुझे लगता है कि यह एक महान दृष्टिकोण है, और पढ़ने के बजाय लिखने पर काम करने के नोएसक्यूएल मॉडल को फिट करता है। बेशक, यह पूरी तरह से यादृच्छिक नहीं होगा - अगर आपको हमेशा एन अनुक्रमिक प्रविष्टियां मिलती हैं तो उपयोगकर्ता कभी-कभी एक दूसरे के बगल में एक ही रिकॉर्ड देखता है। लेकिन यह ओपी के लिए पर्याप्त यादृच्छिक हो सकता है। (आप विभिन्न यादृच्छिक संख्याओं के साथ कई सैकड़ों भी संपत्तियां बना सकते हैं और घुमाएंगे कि आप किस इंडेक्स से आकर्षित करते हैं।) – npdoty

4

आप किस प्रकार के व्यापार की तलाश में हैं? यदि आप इन इकाइयों को डालने पर एक छोटे से प्रदर्शन हिट के साथ तैयार करने के इच्छुक हैं, तो आप उनमें से एन को बहुत जल्दी प्राप्त करने के लिए एक समाधान बना सकते हैं।

जब आप अपने संस्थाओं डालें, कुंजी निर्दिष्ट करें:

यहाँ आप क्या करने की जरूरत है। आप 1 से शुरू होने और वहां से ऊपर जाने के क्रम में अपनी संस्थाओं को चाबियाँ देना चाहते हैं। (इसके लिए कुछ प्रयासों की आवश्यकता होगी, क्योंकि ऐप इंजन में ऑटोइनक्रिएशन() नहीं है, इसलिए आपको किसी अन्य इकाई में उपयोग की जाने वाली अंतिम आईडी का ट्रैक रखना होगा, चलिए इसे एक आईडीजनेटर कहते हैं)

अब जब आपको आवश्यकता हो एन यादृच्छिक संस्थाएं, 1 के बीच एन यादृच्छिक संख्याएं उत्पन्न करती हैं और आपके द्वारा जेनरेट की गई अंतिम आईडी जो भी थी (आपका आईडीजीनरेटर यह जानता होगा)। फिर आप एन चाबियों का उपयोग करके कुंजी द्वारा एक बैच प्राप्त कर सकते हैं, जिसे केवल डेटास्टोर के लिए एक यात्रा की आवश्यकता होगी, और एक क्वेरी से भी तेज़ होगा, क्योंकि कुंजी आमतौर पर पूछताछ से तेज होती है, AFAIK।

इस विधि में कुछ कष्टप्रद विवरण के साथ काम की आवश्यकता होती है:

  1. आपका IdGenerator अड़चन बन सकता है अगर आप मक्खी (अधिक कुछ एक सेकंड से भी) पर इन वस्तुओं की बहुत सारी डालने कर रहे हैं, जो आवश्यकता होगी कुछ प्रकार के sharded IdGenerator कार्यान्वयन।यदि यह सब डेटा प्रीलोड किया गया है, या उच्च मात्रा नहीं है, तो आपके पास यह आसान है।
  2. आपको लगता है कि कुछ आईडी में वास्तव में इसके साथ कोई इकाई नहीं है, क्योंकि आपने इसे हटा दिया है या क्योंकि एक put() कहीं विफल रहा है। यदि ऐसा हुआ तो आपको एक और यादृच्छिक इकाई पकड़नी होगी। (आप कल्पना हो और इस की संभावना को कम करना चाहता है तो आप "छेद को भरने के लिए" पुन: उपयोग करने IdGenerator को यह ईद उपलब्ध कर सकता है)

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

+1

आप आईडी के लिए ऐप इंजन के अंतर्निहित नंबरिंग का उपयोग करके इसे कम या कम कार्यान्वित कर सकते हैं - यदि आप अधिकतम आईडी जानते हैं, आप यादृच्छिक रूप से कुछ समान रूप से चुन सकते हैं। कुछ मौजूद नहीं होंगे, इसलिए उन्हें नए यादृच्छिक आईडी के साथ पुनः प्रयास करें, और बहुत आगे। यदि आपकी आईडी स्पेस घनी है, तो यह ठीक काम करेगी। –

+0

मीठा। मुझे नहीं पता था कि हम 1 से शुरू होने के लिए निर्मित नंबर पर भरोसा कर सकते हैं और वहां से 1 से 1 तक जा सकते हैं। –

+0

आप नहीं कर सकते - लेकिन यह ब्लॉक में आवंटित होगा, और जब तक कि ब्लॉक _mostly_ उपयोग किए जाएंगे, तब तक आपकी रीट्री को प्रबंधित करने के लिए पर्याप्त छोटा होना चाहिए। –

0

मुझे बस एक ही समस्या थी। मैंने डेटास्टोर में अपनी पहले से मौजूद प्रविष्टियों को आईडी असाइन न करने का निर्णय लिया और ऐसा किया, क्योंकि मेरे पास पहले से ही एक शापित काउंटर से कुल राशि थी।

यह "कुल गणना" प्रविष्टियों से "गिनती" प्रविष्टियों का चयन करता है, कुंजी द्वारा क्रमबद्ध।

# select $count from the complete set 
    numberlist = random.sample(range(0,totalcount),count) 
    numberlist.sort() 

    pagesize=1000 

    #initbuckets 
    buckets = [ [] for i in xrange(int(max(numberlist)/pagesize)+1) ] 
    for k in numberlist: 
     thisb = int(k/pagesize) 
     buckets[thisb].append(k-(thisb*pagesize)) 
    logging.debug("Numbers: %s. Buckets %s",numberlist,buckets) 

    #page through results. 

    result = [] 
    baseq = db.Query(MyEntries,keys_only=True).order("__key__") 
    for b,l in enumerate(buckets): 
     if len(l) > 0: 
      result += [ wq.fetch(limit=1,offset=e)[0] for e in l ] 

     if b < len(buckets)-1: # not the last bucket 
      lastkey = wq.fetch(1,pagesize-1)[0] 
      wq = baseq.filter("__key__ >",lastkey) 

खबरदार है कि मेरे पास यह कुछ हद तक जटिल है, और मैं अभी भी conviced है कि मैं न बंद-एक करके या बंद-दर-एक्स त्रुटि नहीं कर रहा हूँ।

और सावधान रहें कि यदि गणना कुल गणना के करीब है तो यह बहुत महंगा हो सकता है। और सावधान रहें कि लाखों पंक्तियों पर ऐपेंगिन समय सीमाओं के भीतर ऐसा करना संभव नहीं होगा।

1

मैं स्टीव के उत्तर से सहमत हूं, एक प्रश्न में एन यादृच्छिक पंक्तियों को पुनर्प्राप्त करने का कोई तरीका नहीं है।

हालांकि, एक इकाई को पुनः प्राप्त करने की विधि आमतौर पर ऐसा नहीं करती है कि लौटाए गए परिणामों की व्यवहार्यता समान रूप से वितरित की जाती है। किसी दिए गए इकाई को वापस करने की संभावना इसके यादृच्छिक रूप से असाइन किए गए नंबर और अगले उच्च यादृच्छिक संख्या के अंतर पर निर्भर करती है। जैसे यदि यादृच्छिक संख्या 1,2, और 10 असाइन की गई हैं (और संख्या 3-9 में से कोई भी नहीं), तो एल्गोरिदम "1" से 8 गुणा अधिक बार "2" वापस कर देगा।

मैंने इसे थोड़ा अधिक विस्तारित तरीके से तय किया है। अगर कोई दिलचस्पी लेता है, तो मुझे

-1

साझा करने में प्रसन्नता हो रही है यदि मैं सही ढंग से समझता हूं, तो आपको एन यादृच्छिक उदाहरण पुनर्प्राप्त करने की आवश्यकता है।

यह आसान है। बस केवल कुंजी के साथ पूछताछ करें। और यादृच्छिक.चॉइस कुंजी के सूची परिणाम पर एन बार करें। फिर चाबियाँ लाकर परिणाम प्राप्त करें।

keys = MyModel.all(keys_only=True) 

n = 5 # 5 random instance 

all_keys = list(keys) 
result_keys = [] 

for _ in range(0,n) 
    key = random.choice(all_keys) 
    all_keys.remove(key) 
    result_keys.append(key) 

# result_keys now contain 5 random keys. 
+0

और यदि आपके डेटा स्टोर में लाखों इकाइयां हैं? डेटा स्टोर से सभी चाबियाँ लोड करें - खराब लगता है ... – aloo

+0

@aloo यदि आपके पास इतने सारे उदाहरण हैं, तो आप डेटास्टोर और मेमकैच में कुल संख्या ट्रैक ट्रैक कर सकते हैं, फिर आप नंबर की सीमा पर 'random.choice' करें 0 और कुल संख्या के बीच। और आपके द्वारा जेनरेट की गई इंडेक्स के साथ बस कुंजी पर फिर से चलने के बाद। या बस सीमा और ऑफ़सेट का उपयोग करें। –

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