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

Posted

技术标签:

【中文标题】如何将 Player、Match 和 EloRank 建模为 NDB 实体【英文标题】:How to model Player, Match, and EloRank as NDB entities 【发布时间】:2013-11-23 19:20:27 【问题描述】:

我正试图围绕 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)但是我如何例如更改玩家的名称而不诉诸对每个匹配实体进行更新? StructuredProperty 似乎也不是答案,因为它们属于定义实体。

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

更新 按照 M12 的建议,使用 KeyProperty 而不是 StringProperty

【问题讨论】:

【参考方案1】:

首先,您可能希望使用 ndb.KeyProperty() 而不是 StringProperty() 来存储玩家密钥。

如果您存储参与每场比赛的球员的引用(密钥),则无需在用户更改名称时更新每场比赛,因为当用户请求比赛时,应用程序可以使用球员的键来获取他们的名字并将其发送回给用户。

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

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

这种方法需要您编写一个相当可靠的框架,以确保在每次比赛后,所有用户的得分都得到适当的修改。 “每场比赛得分”仍然可以在 Match 模型中,但 Player 模型将具有所有比赛的“汇总”得分。

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

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

Player.matches 本质上是用户所玩比赛的键列表,以便在查看球员详细信息和比赛历史时更容易获取。

或者,如果您想存储有关已玩比赛的其他信息,Player.matches 可以是 ndb.JsonProperty(),因为我最初建议的那个 (ndb.KeyProperty(repeated=True)) 的内容相当有限可以存储(只是一个列表)

希望这会有所帮助!

【讨论】:

谢谢。是的,KeyProperty 似乎是个好主意,但这只会给我一个类型检查,以便我只能将匹配键分配给匹配属性等。我想知道的是如何将这个模型“公式化”为一个实体组. 您不会因为比赛不属于单个玩家。每场比赛都是自己的小组。让 Player 成为 EloRank 的祖先是有意义的 - 它属于 Players 实体组,那么 Player 的 KeyProperty 是多余的。

以上是关于如何将 Player、Match 和 EloRank 建模为 NDB 实体的主要内容,如果未能解决你的问题,请参考以下文章

androidexoplayer固定宽高大小

如何动态更改 Youtube Player videoID

Music+ Player的隐私声明

如何将 NSString 从 CamelCase 转换为 TitleCase,将“playerName”转换为“Player Name”?

如何根据分数查找1对1比赛的评分?

Python MYSQL重复问题[重复]