2015-01-20 3 views
0

Скажите, что у меня есть RootEntity, AEntity (ребенок от RootEntity), BEntity (ребенок AEntity).Google app engine: лучший способ сделать запрос

class RootEntity(ndb.Model): 
    rtp = ndb.StringProperty() 

class AEntity(ndb.Model): 
    ap = ndb.IntegerProperty() 

class BEntity(ndb.Model): 
    bp = ndb.StringProperty() 

Таким образом, в различных обработчиков мне нужно получить экземпляры BEntity с конкретным предка (например, из AEntity).

Существует мой запрос: BEntity.query(ancestor = ndb.Key("RootEntity", 1, "AEntity", AEntity.query(ancestor = ndb.Key("RootEntity", 1)).filter(AEntity.ap == int(some_value)).get().key.integer_id()))

Как я могу оптимизировать этот запрос? Сделать лучше, может быть менее сложным?

Upd:

Этот запрос является частью функции с @ndb.transactional декоратора.

ответ

0

Существует запрос и запрос с запросами предков. Они более сложны и беспорядочны, но вы получаете лучшую структуру для своих данных и согласованности в своих запросах.

Чтобы упростить это, если ваш обработчик знает, какой BEntity вы хотите получить, просто пройдите по закодированному ключу key.urlsafe(), он уже закодировал всю информацию вашего предка.

Если это невозможно, попробуйте перестроить ваши данные. Поскольку эти объекты являются одним и тем же предком, они принадлежат к одной и той же группе сущностей, поэтому вы можете вставить/обновить ~ 1 раз в секунду для объектов в этой группе сущностей. Если вам требуется более высокая пропускная способность или вы не требуете согласованных исконных запросов, попробуйте использовать ndb.KeyProperty для связывания объектов со ссылкой на родителя, а не как с предком. Тогда вам нужно будет получить только одного родителя для запроса, а не родителя и родителя родителя.

Вы должны также попытаться использовать идентификаторы всякий раз, когда это возможно, так что вы можете избежать необходимости фильтровать сущностей в хранилище данных по свойствам и просто ссылаться на них по ID:

BEntity.query(ancestor = ndb.Key("RootEntity", 1, "AEntity", int(some_value)))

Здесь int(some_value) является целым числом ID AEntity, который вы использовали при создании этого объекта. Просто убедитесь, что вы можете гарантировать, что идентификаторы, которые вы вручную создаете/используете, будут уникальными во всех экземплярах этой модели , которые имеют один и тот же родитель.

РЕДАКТИРОВАТЬ: Чтобы уточнить, мой последний пример должен быть сделаны более ясно, что я предлагал перестроить данные таким образом, что int(some_value) быть использована в качестве целочисленного идентификатора AEntity а не хранить в виде отдельной свойство Сущности - если возможно, конечно. В приведенном примере выполняется запрос для объектов AEntity, которые имеют заданное значение целочисленного поля int(some_value) и выполняются с get() - подразумевая, что вы всегда будете ожидать возвращения одного значения для этого идентификатора целого числа, что делает его хорошим кандидатом для использования в качестве целочисленный идентификатор для ключа этого объекта, исключающий необходимость в запросе.

+0

int (some_value) не является идентификатором целого числа AEntity. Это ap (ndb.IntegerProperty()) этого объекта. –

+0

То, что я пытался сказать, это переключить его на идентификатор целого числа для AEntity вместо отдельного свойства, если это возможно. Из вашего примера запроса это выглядит так, как будто это должно быть уникальным, поскольку вы запрашиваете в поле и выполняете с помощью 'get()', подразумевая, что вы ожидаете только единственную уникальную запись для этого конкретного 'int (some_value)' – someone1

2

Вам не следует использовать группы сущностей для представления отношений сущностей.

Entity groups have a special purpose: определение объема транзакций.Они дают вам возможность обновлять несколько объектов транзакционно, если они являются частью одной и той же группы сущностей (это ограничение несколько смягчилось новым XG transactions). Они также позволяют использовать запросы в транзакциях (недоступные через транзакции XG).

Недостатком групп сущностей является то, что они имеют ограничение на обновление 1 запись/секунду.

В вашем случае мое предложение состояло бы в том, чтобы использовать отдельные объекты и делать ссылки между ними. Ссылка должна быть Ключем ссылочного объекта, поскольку это безопасно для типов.

Что касается простоты запросов: GAE, к сожалению, не поддерживает JOIN или ссылки (многоуровневые), поэтому вам все равно нужно объединить несколько запросов вместе (как и сейчас).

Смежные вопросы