2013-11-23 1 views
1

Я пытаюсь обернуть голову вокруг групп объектов и иерархических ключей в ndb, но я мог бы застрять в «нормализованном мышлении». Я хочу вычислить и сохранить рейтинг разных игроков в зависимости от того, как они делали в разных матчах друг против друга с течением времени. Но все, что я могу придумать, чтобы сохранить «внешние ключи» в виде строки, как это:Как моделировать Player, Match и EloRank как объекты NDB

class Player(ndb.Model): 
    name = ndb.StringProperty()   

class Match(ndb.Model): 
    player1_key = ndb.KeyProperty(kind=Player) # pointing to Player entity 
    player2_key = ndb.KeyProperty(kind=Player) # pointing to Player entity 
    player1_score = ndb.IntegerProperty() 
    player2_score = ndb.IntegerProperty() 
    time = ndb.DatetimeProperty(auto_now_add=True) 

class EloRank(ndb.Model): 
    player_key = ndb.KeyProperty(kind=Player) # pointing to Player entity 
    match_key = ndb.KeyProperty(kind=Match) # pointing to Match entity 
    rank = ndb.IntegerProperty() 
    time = ndb.DatetimeProperty(auto_now_add=True) 

Конечно, это было бы легко «денормализовать» данные по скопировать его (т.е. Match есть два ключа к югу, один для игрока 1 и один для игрока 2), но как я могу, например, изменить имя игрока, не прибегая к выполнению обновлений в каждом объекте Match? StructuredProperty также не является ответом, так как они принадлежат к определяющему объекту.

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

Update Используйте KeyProperty вместо StringProperty как предложено M12.

ответ

0

Прежде всего, вы можете использовать ndb.KeyProperty() для хранения ключей игрока вместо StringProperty().

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

Далее, я бы, вероятно, сохранить ранг игрока в его случае, то есть в модели игрока:

class Player(ndb.Model): 
    name = ndb.StringProperty() 
    rank = ndb.IntegerProperty() 

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

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

class Player(ndb.Model): 
    name = ndb.StringProperty() 
    rank = ndb.IntegerProperty() 
    matches = ndb.KeyProperty(repeated=True) 

Player.matches бы быть по существу список ключей к матчам, которые играет пользователь, так что их легче получить при просмотре сведений о игроках и истории матчей.

В качестве альтернативы, Player.matches может быть ndb.JsonProperty(), если вы хотите сохранить дополнительную информацию о матчах, которые я изначально предложил (ndb.KeyProperty (repeat = True)) довольно ограничен в том, что он может хранить (это только список)

Надеюсь, это поможет!

+0

Спасибо. Да, 'KeyProperty' кажется хорошей идеей, но это просто даст мне проверку типа, так что я могу назначить ключи соответствия свойствам совпадений и т. Д. Мне было интересно, как« сформулировать »эту модель как группу сущностей , – Kalle

+0

Вы не согласитесь, что матч не принадлежит одному игроку. Каждый матч будет его собственной группой. Было бы разумно, чтобы игрок был потомком EloRank - он принадлежит группе лиц Игроков, тогда KeyProperty для Player является избыточным. –