سؤال

أحاول كتابة استعلام GQL الذي يعود إلى سجلات عشوائية لنوع معين. يعمل تطبيقي الحالي ولكنه يتطلب استدعاء N إلى Datastore. أود أن أجعلها مكالمة واحدة إلى DataStore إذا كان ذلك ممكنا.

أنا حاليا تعيين عدد عشوائي لكل نوع أضعه في DataStore. عندما أسأل عن سجل عشوائي، أقوم بإنشاء عدد عشوائي آخر واستعلام عن السجلات> ترتيب ROND عن طريق حد ASC 1.

ومع ذلك، فإن هذا يعمل فقط يعود فقط سجل واحد لذلك أحتاج إلى الاستفسارات N. أي أفكار حول كيفية جعل هذا الاستعلام واحد؟ شكرا.

هل كانت مفيدة؟

المحلول

"تحت غطاء محرك السيارة" يمكن استدعاء استعلام بحث واحد فقط إرجاع مجموعة من الصفوف المتتالية من بعض الفهرس. هذا هو السبب في أن بعض استفسارات GQL، بما في ذلك أي استخدام! =، قم بتوسيع مكالمات متعددة البيانات.

n التحديدات العشوائية العسكرية المستقل ليست (بشكل عام) متتالية في أي فهرس.

كيد.

ربما يمكنك استخدام MEMCACHER لتخزين الكيانات، وتقليل تكلفة الاستيلاء على N منهم. أو إذا كنت لا تمانع في التحديدات "العشوائية" تقارب معا في الفهرس، حدد كتلة مختارة عشوائيا من (قل) 100 في استعلام واحد، ثم اختر N عشوائيا من تلك. نظرا لأن لديك حقل عشوائي بالفعل، فلن يكون من الواضح فورا على فوري على أن العناصر N ذات صلة. على الأقل، ليس حتى ينظر إلى الكثير من العينات ولاحظ أن العناصر A و Z لا تظهر أبدا في نفس المجموعة، لأنها أكثر من 100 بصرف النظر في الفهرس المعشمي. وإذا سمح للأداء، يمكنك إعادة عشوائي كياناتك من وقت لآخر.

نصائح أخرى

أي نوع من المفاضلات التي تبحث عنها؟ إذا كنت على استعداد لطرح أداء صغير تضرب على إدراج هذه الكيانات، فيمكنك إنشاء حلا للحصول على نهم بسرعة كبيرة.

إليك ما تحتاج إلى القيام به:

عند إدراج كياناتك، حدد المفتاح. تريد إعطاء مفاتيح للكيانات الخاصة بك في النظام، بدءا من 1 والاستعداد من هناك. (سيتطلب ذلك بعض الجهد، حيث لا يحتوي محرك التطبيق على AutoIncract () لذلك ستحتاج إلى تتبع المعرف الأخير الذي استخدمته في بعض الكيان الآخر، دعونا نسميها حيادا)

الآن عندما تحتاج إلى كيانات عشوائية، قم بإنشاء أرقام عشوائية N بين 1 وبما هو المعرف الأخير الذي قمت بإنشائه كان (سيعرف idgenerator هذا). يمكنك بعد ذلك إجراء دفعة واحدة باستخدام مفتاح مفاتيح N، والتي ستتطلب فقط رحلة واحدة إلى Datastore، وسوف تكون أسرع من الاستعلام أيضا، لأن المفتاح يحصل بشكل أسرع بشكل عام من الاستفسارات، AFAIK.

تتطلب هذه الطريقة التعامل مع عدد قليل من التفاصيل المزعجة:

  1. قد يصبح IDGEGenerator الخاص بك عنق الزجاجة إذا كنت تقوم بإدراج الكثير من هذه العناصر على الطاير (أكثر من بضعة ثانية واحدة)، والتي ستحتاج إلى نوع من تطبيق الشارد للهواء. إذا كانت كل هذه البيانات محملة مسبقا، أو أنها ليست عالية الحجم، فأنت سهلة.
  2. قد تجد أن بعض المعرف لا يحتوي بالفعل كيان مرتبط به بعد الآن، لأنك حذفت أو لأن وضع () فشل في مكان ما. إذا حدث هذا، فسيتعين عليك الاستيلاء على كيان عشوائي آخر. (إذا كنت ترغب في الحصول على تخيل وتقليل احتمالات ذلك، فيمكنك إتاحة هذا المعرف لل IDGENERATOR لإعادة استخدام "ملء الثقوب")

لذلك يأتي السؤال إلى مدى السرعة التي تحتاجها هذه العناصر n مقابل عدد المرات التي ستضيفها وحذفها، وما إذا كان التعقيد الإضافي القليل يستحق دفع هذا الأداء.

يبدو أن الطريقة الوحيدة هي عن طريق تخزين القيمة العدد الصحيحة العشوائية في خاصية كل كيان خاص والاستعلام عن ذلك. يمكن القيام بذلك تلقائيا تماما إذا أضفت مجرد خاصية تهيئة تلقائيا.

لسوء الحظ، سيتطلب ذلك معالجة جميع الكيانات بمجرد ملأت مؤخرة البيانات الخاصة بك بالفعل.

إنه غريب، وأنا أعلم.

أوافق على الإجابة من ستيف، لا توجد طريقة لاسترداد الصفوف العشوائية في استعلام واحد.

ومع ذلك، حتى طريقة استرداد كيان واحد لا يعمل عادة بحيث يتم توزيع براءة النتائج التي تم إرجاعها بالتساوي. يعتمد احتمال إعادة كيان معين على الفجوة لعدد محدد بشكل عشوائي ورقم عشوائي أعلى المقبل. على سبيل المثال إذا تم تعيين أرقام عشوائية 1،2، و 10 (وليس من الأرقام 3-9)، فإن الخوارزمية ستعود "2" 8 مرات في كثير من الأحيان أكثر من "1".

لقد قمت بإصلاح هذا بطريقة أكبر قليلا. إذا كان شخص ما مهتما، فأنا سعيد بمشاركة

أنا فقط كان نفس المشكلة. قررت عدم تعيين معرفات إدخالاتي الموجودة بالفعل في Datastore وفعلت هذا، كما كان لدي بالفعل TotalCount من عداد شارد.

يؤدي هذا إلى تحديد إدخالات "العد" من إدخالات "TotalCount"، مرتبة حسب مفتاح.

    # 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)

احذر أن هذا مجمع إلى حد ما، وما زلت لم أكن أعقد أنني لا أمتلك أخطاء خارجية أو خارجية.

وأحذر من أنه إذا كان العد قريب من TotalCount، فقد يكون هذا مكلفا للغاية. وحذر من أنه على الملايين من الصفوف قد لا يكون من الممكن القيام به ضمن حدود وقت Appengine.

إذا فهمت بشكل صحيح، فأنت بحاجة إلى استرداد مثيل عشوائي.

من السهل. فقط هل الاستعلام مع المفاتيح فقط. وفعل عشوائي N مرات في قائمة النتائج للمفاتيح. ثم احصل على النتائج عن طريق جلب المفاتيح.

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.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top