2010-08-10 12 views
15

कुछ इस तरह वर्तमान में मैं उपयोग कर रहा हूँ:डेटास्टोर (AppEngine) में कुछ यादृच्छिक कैसे प्राप्त करें?

images = Image.all() 
    count = images.count() 
    random_numb = random.randrange(1, count) 
    image = Image.get_by_id(random_numb) 

लेकिन यह पता चला है कि AppEngine पर डेटासंग्रह में आईडी से 1. मैं डेटासंग्रह में दो छवियों है शुरू नहीं करेंगे और अपने आईडी 6001 कर रहे हैं और 7001.

यादृच्छिक छवियों को पुनर्प्राप्त करने का कोई बेहतर तरीका है?

उत्तर

17

डेटास्टोर वितरित किया जाता है, इसलिए आईडी गैर-अनुक्रमिक हैं: दो डेटास्टोर नोड्स को बिना किसी संघर्ष के एक आईडी उत्पन्न करने में सक्षम होना चाहिए।

यादृच्छिक इकाई प्राप्त करने के लिए, आप प्रत्येक इकाई को 0 और 1 के बीच एक यादृच्छिक फ्लोट संलग्न कर सकते हैं। तब क्वेरी करने के लिए, कुछ इस तरह करते हैं:

rand_num = random.random() 
entity = MyModel.all().order('rand_num').filter('rand_num >=', rand_num).get() 
if entity is None: 
    entity = MyModel.all().order('rand_num').get() 

संपादित करें: निक के सुझाव के अनुसार अपडेट किया गया गिरावट के माध्यम से मामले।

+4

'इकाई कोई नहीं है' मामले में, आपको केवल 'rand_num' द्वारा आदेशित पहली इकाई प्राप्त करनी चाहिए, इस प्रकार एक गोलाकार बफर जैसे इकाइयों का इलाज करना चाहिए। जिस तरह से आप वर्तमान में ऐसा कर रहे हैं, आखिरी इकाई को अन्य सभी की तुलना में बहुत अधिक चुना जा सकता है। –

+0

यह क्वेरी कैसे अनुक्रमित की जाएगी यदि बिल्कुल? मुझे इसके लिए एक समाधान लागू करना पड़ा और इस प्रकार की क्वेरी की दक्षता की कमी के डर के लिए इस विधि का चयन नहीं किया। सुनिश्चित नहीं है कि मेरे डर की स्थापना की गई है (नीचे समाधान देखें)। –

+0

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

1

एक और (कम कुशल) विधि, जिन्हें सेटअप की आवश्यकता है:

query = MyModel.all(keys_only=True) 

# query.filter("...") 

selected_key = None 
n = 0 
for key in query: 
    if random.randint(0,n)==0: 
    selected_key = key 
    n += 1 

# just in case the query is empty 
if selected_key is None: 
    entry = None 
else: 
    entry = MyModel.get(selected_key) 
10

एक अन्य समाधान (आप एक अतिरिक्त संपत्ति में शामिल नहीं करना चाहते हैं)। स्मृति में कुंजी का एक सेट रखें।

import random 

# Get all the keys, not the Entities 
q = ItemUser.all(keys_only=True).filter('is_active =', True) 
item_keys = q.fetch(2000) 

# Get a random set of those keys, in this case 20 
random_keys = random.sample(item_keys, 20) 

# Get those 20 Entities 
items = db.get(random_keys) 

ऊपर कोड केवल कुंजी हो रही है और फिर एक यादृच्छिक सेट जो के साथ एक बैच प्राप्त करने के लिए बनाने के लिए बुनियादी विधि को दिखाता है। आप स्मृति के उस सेट को स्मृति में रख सकते हैं, जब आप नई ItemUser इकाइयां बनाते हैं तो इसमें जोड़ें, और फिर एक विधि है जो n यादृच्छिक संस्थाएं देता है। Memcached कुंजी का प्रबंधन करने के लिए आपको कुछ ओवरहेड लागू करना होगा। मुझे यह समाधान बेहतर लगता है यदि आप अक्सर यादृच्छिक तत्वों के लिए क्वेरी कर रहे हैं (मुझे लगता है कि n के लिए बैच का उपयोग करना मानें n इकाइयों के लिए क्वेरी से अधिक कुशलताएं हैं।

+0

हम इसे एनडीबी पर कैसे लागू कर सकते हैं? गिनती() प्रदर्शन समस्या को हल करने के लिए –

6

मुझे लगता है कि ऊपर ड्रू सीअर्स का उत्तर (बनाने पर प्रत्येक इकाई को एक यादृच्छिक फ्लोट संलग्न करें) में संभावित समस्या है: प्रत्येक आइटम में उठाए जाने का बराबर मौका नहीं होता है। उदाहरण के लिए, यदि केवल 2 इकाइयां हैं, और एक को 0.249 9 का rand_num मिलता है, और दूसरा 0.25 हो जाता है, 0.25 एक लगभग हर समय उठाया जाएगा। यह आपके आवेदन से कोई फर्क नहीं पड़ता है या नहीं। जब भी इसे चुना जाता है, तो आप किसी इकाई के rand_num को बदलकर इसे ठीक कर सकते हैं, लेकिन इसका मतलब है कि प्रत्येक पढ़ने के लिए भी एक लेखन की आवश्यकता होती है।

और पिक्स का उत्तर हमेशा पहली कुंजी का चयन करेगा।

यहाँ सबसे अच्छा सामान्य प्रयोजन समाधान मैं के साथ आ सकता है:

num_images = Image.all().count() 
offset = random.randrange(0, num_images) 
image = Image.all().fetch(1, offset)[0] 

कोई अतिरिक्त जरूरत गुण है, लेकिन नकारात्मक पक्ष यह है कि गिनती() और लाने() दोनों प्रदर्शन निहितार्थ है है अगर छवियाँ की संख्या बड़ा है।

+0

, मैं शेरिंगकाउंटर्स का उपयोग करता हूं (https://developers.google.com/appengine/articles/sharding_counters) – John

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