如何将 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 实体的主要内容,如果未能解决你的问题,请参考以下文章
如何将 NSString 从 CamelCase 转换为 TitleCase,将“playerName”转换为“Player Name”?