Запрос NDB для повторяющегося структурированного свойства по предку

Я тестирую следующий объект:

pk = ndb.Key(League, 'Premier League', 'Season', '2012/13')
o = Team(
    id = 'Chelsea',
    name ='Chelsea',
    leagues = [
       TeamInLeague(
           parent = pk,
           position = 1,
       ),],
)
o.put()

и следующий тест не проходит на AssertionError: 0 != 1:

q = Team.query(ancestor=pk)
self.assertEqual(q.count(), 1)

Я также попробовал следующий тест:

q = Team.query(TeamInLeague(ancestor=pk))
self.assertEqual(q.count(), 1)

И это терпит неудачу на AttributeError: type object 'TeamInLeague' has no attribute 'ancestor'.

Есть ли способ сделать запрос по родителю структурированного свойства? Или я все делаю не так? Из документов я понял, что добавляю родительское свойство при создании.


person Neara    schedule 16.09.2012    source источник


Ответы (1)


Вы не можете использовать отношения предков, чтобы делать то, что вы хотите.

На самом деле вы не предоставляете родительский ключ при создании своего командного класса. Насколько я понимаю, вы хотите, чтобы объект Team был создан с объектом League в качестве родителя?

Это будет выглядеть так:

league_k = ndb.Key(League, 'Premier League', 'Season', '2012/13')
o = Team(
    id = 'Chelsea',
    name ='Chelsea',
    parent = league_k
)
o.put()

Однако в вашей модели данных будет недостаток. Класс команды навсегда будет связан с Лигой. Поскольку Лига, по-видимому, содержит сезон, ваша команда будет недоступна в следующем сезоне.

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

Кроме того, не обязательно указывать все свойства объекта в конструкторе. Это не jQuery. Во многих случаях удобнее создавать объектные отношения после того, как вы создали объект и перед вызовом put().

Ваш код будет выглядеть так:

league_k = ndb.Key(League, 'Premier League', 'Season', '2012/13')
team = Team(id = 'Chelsea', name ='Chelsea')
o.put()
team_in_league = TeamInLeague(team=team.key(), league=league_k, pos=1)
team_in_league.put()
person Hans Then    schedule 16.09.2012
comment
Хорошо, да, я вижу, как это будет работать лучше. Моей первой реакцией было пойти по этому пути, но потом мне сказали, что родительский ключ — более интересный способ сделать это. Спасибо за такой быстрый ответ. - person Neara; 16.09.2012
comment
Насколько я понимаю, использование отношений предков делается для того, чтобы транзакции могли выполняться на этих объектах. Однако диспетчеру хранилища также будет предложено хранить данные на том же узле или диске. - person Hans Then; 16.09.2012