如何将Player,Match和EloRank建模为NDB实体

时间:2013-11-23 19:20:27

标签: google-app-engine app-engine-ndb

我试图围绕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似乎也不是答案,因为它们属于定义实体。

您如何重写此模型以将实体放在同一组中?

更新 按照M12的建议使用KeyProperty代替StringProperty

1 个答案:

答案 0 :(得分:0)

首先,您可能希望使用ndb.KeyProperty()来存储播放器键而不是StringProperty()。

如果您将参考(密钥)存储到参与每场比赛的玩家,则当用户更改名称时您不需要更新每场比赛,因为当用户请求匹配时,应用程序可以使用该玩家的用于获取其姓名并将其发回给用户的密钥。

接下来,我可能会将玩家的等级存储在他的实例中,即在玩家模型中:

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

这种方法要求您编写一个相当可靠的框架,以确保在每次匹配后,所有用户得分都会得到适当修改。 “每场比赛得分”仍然可以在比赛模型中,但是球员模型将具有所有比赛的“聚合”分数。

为了做到这一点,将每个玩家所扮演的比赛列表添加到他们的模型中也很方便,所以玩家模型现在将是:

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

Player.matches实际上是用户所进行比赛的键列表,以便在查看玩家详细信息和比赛历史时更容易获取。

或者,如果你想存储有关比赛的其他信息,那么Player.matches可能是一个ndb.JsonProperty(),因为我最初建议的那个(ndb.KeyProperty(重复=真))在它的内容相当有限可以存储(它只是一个列表)

希望这有点帮助!