1

Сборная команда может быть развернута с течением времени для нескольких проектовКак эффективно создавать подзапросы app-engine-ndb для свойств связанных объектов KeyProperty?

В этом примере я хочу запросить команды, назначенные только для «активных» проектов. Код, который я использую, работает, но я хотел бы знать, есть ли более эффективные/компактные средства для этого.

Модели

class Team(ndb.Model): 
    """Model for representing an project team.""" 
    teamid = ndb.StringProperty(required=True) 
    project = ndb.KeyProperty(kind='Project', required=True, repeating=True) 

class Project(ndb.Model): 
    """Model for representing a Project""" 
    name = ndb.StringProperty(required=True) 
    status = ndb.StringProperty(required=True) 

Запрос

status = 'active' 

project_query = Project.query()\ 
    .filter(Project.status == status) 

active_projects = project_query.fetch(1000, keys_only=True) 

team_query = Team.query().order(Team.teamid)\ 
    .filter(Team.projectid.IN(active_projects)) 

results = team_query.fetch(max_results, offset=start_at) 

Компактная форма (по существу то же самое)

team_query = Team.query().order(Team.teamid)\ 
    .filter(Team.projectid.IN(Project.query().filter(Project.status == status) 
     .fetch(1000, keys_only=True))) 

Есть ли лучший способ?

+0

Проверка [Appstats] (https: // облако .google.com/appengine/docs/python/tools/appstats? hl = ru) будет вашим лучшим способом сказать наверняка. Вы должны обязательно выполнить запрос 'keys_only =' для активных проектов, а затем использовать эти ключи в запросе для 'Team'. –

+0

вот что я делаю уже. компактная форма не отличается от сравнения - мне было интересно, есть ли принципиально другой способ справиться с ней. – Jonathon

+1

Нет, ваш путь наиболее эффективен с учетом контекста в вашем сообщении. –

ответ

2

Вы можете де-нормализовать свою модель данных, «избыточно», имея свойство project_status на объекте Team, а также поддерживаемое таким же, как свойство status на соответствующем объекте проекта.

Недостатком, конечно же, является то, что для «изменения статуса проекта» также необходимо найти все команды, назначенные этому проекту, и соответственно изменить их project_status (и для этого вам может понадобиться транзакция с несколькими объектами). Но большой потенциал заключается в том, что поиск всех команд, назначенных для проектов в определенном статусе, становится намного быстрее, одним простым запросом.

Этот компромисс довольно типичен для решений, связанных с де-нормализацией моделей данных. Если в вашем приложении статус проекта изменяется относительно редко (и, возможно, обычно несколько команд назначаются для данного проекта), в то время как запросы для «всех команд, назначенных проектам в определенном статусе», являются частыми и должны быть быстрыми, -нормализация будет достойной оптимизацией.

Ускорение еще более абстрактного, что де-нормировки стоит, всегда сильно зависит от конкретных ограничений приложения - какие запросы или обновления встречаются редко или часто, какие цели производительности существуют для каждой операции. Вы также всегда платите цену за немного больше данных, так как несколько вещей дублируются. С другой стороны, многие приложения имеют относительно редкие записи/обновления и довольно часто читаемые/запросы, что, как правило, способствует разумной де-нормализации.

1

Потому что у вас есть много-ко-многим между группами и проектами, это ваш выбор будет ли иметь Команды:

project = ndb.KeyProperty(kind='Project', required=True, repeating=True) 

или проекты с:

team = ndb.KeyProperty(kind='Team', required=True, repeating=True) 

Вы можете улучшить ваш запрос в запросе, используя только один запрос и ndb.get_multi(). Запросы медленные, происходит быстрее (особенно когда memcached). Изменяя свои модели, вы можете улучшить свои запросы.

class Team(ndb.Model): 
    """Model for representing an project team.""" 
    teamid = ndb.StringProperty(required=True) 

class Project(ndb.Model): 
    """Model for representing a Project""" 
    name = ndb.StringProperty(required=True) 
    status = ndb.StringProperty(required=True) 
    team = ndb.KeyProperty(kind='Team', required=True, repeating=True) 

Теперь вы можете запросить по статусу и выполнить ПОЛУЧАЕТЕ: (. Кредит Тиму Хоффмана для комментирования этого подхода)

status = 'active' 

project_query = Project.query()\ 
    .filter(Project.status == status) 

active_projects = project_query.fetch(1000, keys_only=True) 

teams = set() 
for project in active_projects: 
    teams.extend(project.team) 

results = ndb.get_multi(list(teams)) 

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

  • Нет связанных вопросов^_^