الطريقة الأكثر كفاءة لتتناسب مع عدد معين من العناصر في قائمة DB.ModelProperty
-
20-09-2019 - |
سؤال
بالنسبة إلى هذا سؤال مختلف ولكن ليس غير مرتبط سوف أستعير النماذج المثالة.
class Foo(db.Model): bars = db.ListProperty(db.Key)
class Bar(db.Model): pass
إذا كان لدي كيان فو معين وأريد الحصول على جميع كيانات فو الأخرى التي تحتوي أيضا على مفتاح شريط معين في أشرطة الحانات الخاصة به، فسأي استخدام الاستعلام التالي:
related_foos = Foo.all().filter('bars', bar_entity).fetch(fetch_count)
ماذا عن ما إذا كنت أرغب في العثور على جميع الكيانات الأخرى في طراز النموذج فو الذي يحتوي على عدد N على الأقل من كيانات شريط المطابقة؟ إن الطريقة الواضحة للقيام بذلك مع حلقة لا تنطوي على أوجه القصور الحاد، وقد يكون من الأفضل تغيير النموذج نفسه فعليا لجعل هذا أسهل، لكنه لا يبدو واضحا كيفية القيام بذلك.
المحلول
بالنظر إلى سجل فو يحتوي على 10 bar_entities والبحث عن جميع سجلات فو التي لديها ما لا يقل عن 2 من هذه الكيانات العشر ستؤدي إلى 45 قيم المساواة المحتملة 10! / (2! * (10-2)!) = 45.
يمكن استنتاج ذلك في 10_c_ (2-1) = 10 يقرأ.
SELECT * from table WHERE bar="1" AND bar in ["2", "3", "4", "5", "6", "7", "8", "9", "0"]
SELECT * from table WHERE bar="2" AND bar in ["3", "4", "5", "6", "7", "8", "9", "0"]
SELECT * from table WHERE bar="3" AND bar in ["4", "5", "6", "7", "8", "9", "0"]
etc.
لتقليل ذلك إلى قراءة واحدة سيتطلب ذلك عند إضافة سجل FOO، تقوم بتعبئة جدول منفصل يحتوي على جميع المجموعات 2 للحصول على سجل معين.
Say you had
foo_table
foo1 [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
foo2 [1, 3, 4]
foo3 [1, 2, a]
foo4 [b, 6, c]
foo_combo_2_table
Parent Combination
foo1 12
foo1 13
... and all 45 foo1 combinations each in its own row
foo2 13
foo2 14
foo2 34
foo3 12
foo3 1a
foo3 2a
etc.
Now you can do a
indexes = SELECT __KEY__ from foo_combo_2_table WHERE combination IN [12, 13, 14, 15, ... all 45]
keys = [k.parent() for k in indexes] # you would need to filter for duplicates
وبهذه الطريقة لن تدخل في أي مشكلات فهرس تنفجر.
إذا كنت ترغب أيضا في القيام بأي كيانات 3 أو أي 4 من كل من كل منها، فستحتاج إلى إنشاء عدد من القراءات Foo_Combo_n_table أو القيام بعمل 10_c_ (N-1) من القراءات.
نصائح أخرى
يمكنك ببساطة تطبيق نفس المرشح بشكل متكرر:
related_foos = Foo.all().filter('bars', bar_entity).filter('bars', bar_entity_2).fetch(fetch_count)
أو، مدفوعة البيانات:
q = Foo.all()
for bar in bar_entities:
q.filter('bars', bar)
related_foos = q.fetch(fetch_count)
إذا لم تقم بتطبيق أي عدم المساواة أو ترتيب الطلبات إلى الاستعلام، فسيتمكن DataStore من تنفيذ الاستعلامات باستخدام الفهارس المدمجة واستراتيجية الانضمام إلى دمج، بغض النظر عن عدد المرشحات التي تطبقها. إذا كنت بحاجة إلى عدم المساواة أو ترتيب الفرز، فستحتاج إلى أن يكون لديك فهرس لكل عدد من الأشرطة التي قد ترغب في التصفية، مما يؤدي إلى انفجار الفهارس (وهكذا يتم تجنبه بشكل أفضل!)