如何在没有谷歌应用引擎读取的数据存储区的情况下从实体实例获取引用的实体属性的键名?

时间:2012-04-02 17:05:37

标签: python google-app-engine

考虑我有以下模型 -

class Team(db.Model): # say I have just 5 teams
  name = db.StringProperty()

class Player(db.Model): # say I have thousands of players
  name = db.StringProperty()
  team = db.ReferenceProperty(Team, collection_name="player_set")
  1. 每个团队实体的键名='team_',以及每个玩家实体='玩家_'

  2. 通过一些事先的安排,我可以使用Team实体(key_name,name)映射。例如(team_01,美国),(team_02,俄罗斯)等

  3. 我必须在页面上显示所有玩家及其团队。这样做的一种方法是 -

    players = Player.all().fetch(1000) # This is 1 DB read
    for player in players: # This will iterate 1000 times
      self.response.out.write(player.name) # This is obviously not a DB read
      self.response.out.write(player.team.name) #This is a total of 1x1000 = 1000 DB reads
    
  4. 这是一个1001 DB读取一个愚蠢的事情。

  5. 有趣的是,当我对玩家进行db.to_dict()时,它表明对于该列表中的每个玩家都有玩家的“名字”,并且团队中有“key_name”也可以。

  6. 那我该如何做呢?

    players = Player.all().fetch(1000) # This is 1 DB read
    for player in players: # This will iterate 1000 times
      self.response.out.write(player.name) # This is obviously not a DB read
      self.response.out.write(team_list[player.<SOME WAY OF GETTING TEAM KEY NAME>]) # Here 'team_list' already has (key_name, name) for all 5 teams
    
  7. 我一直在努力解决这个问题。已阅读所有可用文档。

    我可以拥抱能帮助我的人: - )

    免责声明:以上问题描述并非真实情况。这是一个简化的安排,完全代表我的问题。我在一个复杂的评估和大GAE应用程序中遇到过它。

4 个答案:

答案 0 :(得分:3)

在你的循环中,Player.team.get_value_for_datastore(player)将返回团队的Key对象而不从数据存储中获取任何内容。

如果你想为一组玩家预先取得所有队伍(假装你有超过5个,那么如果你不需要全部那些就不想取得所有队员),那么{ {3}}解释了一项很好的技巧。

答案 1 :(得分:1)

从您的特定情况开始,降低数据库成本的唯一方法是缓存Team。如果您使用新的NDB API,那么已经为您完成了这项工作。

答案 2 :(得分:1)

如果你有很多玩家通过密钥引用的团队,并且你想在显示团队时列出一些Player属性的子集,并且你想最小化数据库读取,那么你可能需要进行非规范化,并将一些播放器信息的子集缓存在附加到团队的序列化blob(或一大块Json)中。懒惰地重新计算成员变更的blob(如果成员变化的频率低于团队观点,这是一个明确的胜利)。这种更新是后台任务的完美用例。

答案 3 :(得分:0)

ReferenceProperty存储Key。您应该能够使用Key的id_or_name方法获取key_name。