GQL-запрос для эффективного охвата сущностных отношений
Я нахожусь в ситуации, когда мне нужно охватить отношения сущностей Google App Engine в запросе, как в модели базы данных Django. я использую ListProperty
s для отношений один ко многим, вот так:
class Foo(db.Model): bars = db.ListProperty(db.Key)
class Bar(db.Model): eggs = db.ListProperty(db.Key)
И я хотел бы выполнить запрос, который делает следующее:
# Foo.filter('bars.eggs =', target_egg)
[foo
for egg in eggs if egg == target_egg
for eggs in bar.eggs
for bar in foo.bars
for foo in Foo.all()]
Понимание кажется в корне неэффективным. Я действительно хотел бы выполнить запрос, как в закомментированной части, но он не выглядит так, как будто синтаксис GQL допускает запросы к атрибутам атрибутов:
SELECT * FROM <kind>
[WHERE <condition> [AND <condition> ...]]
[ORDER BY <property> [ASC | DESC] [, <property> [ASC | DESC] ...]]
[LIMIT [<offset>,]<count>]
[OFFSET <offset>]
<condition> := <property> {< | <= | > | >= | = | != } <value>
<condition> := <property> IN <list>
<condition> := ANCESTOR IS <entity or key>
1 ответ
Вы правы, хранилище данных App Engine не допускает такого рода запросов. И вы правы, что понимание списка неэффективно. Учтите, однако, что это в значительной степени именно то, что делает реляционная база данных, когда вы выполняете запрос с объединениями, подобными вашему - база данных должна выполнять ту же самую O(n^3) работу, которую вы делаете здесь - единственное отличие состоит в том, что что вы делаете это на Python, и с дополнительным временем поездки туда и обратно. Поскольку App Engine разработан для масштабирования, он не предназначен для такого рода запросов.
Обычно, однако, есть способ, которым вы можете немного денормализовать свою модель, чтобы облегчить это, переместив некоторые свойства, к которым вам нужно получить доступ, в модель Foo, или, если вы делаете агрегаты, переместив итоговое значение в модель Foo. Трудно дать конкретные решения, не зная, какую проблему вы пытаетесь решить.