【问题标题】:In Google App Engine, how do I avoid creating duplicate entities with the same attribute?在 Google App Engine 中,如何避免创建具有相同属性的重复实体?
【发布时间】:2010-09-05 09:17:22
【问题描述】:

我正在尝试添加一个事务以防止创建具有相同属性的两个实体。在我的应用程序中,每次看到新的 Google 用户登录时,我都会创建一个新的播放器。当新的 Google 用户在几毫秒内进行多个 json 调用时,我当前的实现偶尔会创建重复的播放器。当我像这里注释的那样添加交易时,我得到了各种错误。确保我永远不会创建两个具有相同 user_id 的玩家实体的最简单方法是什么?

  def get_player_from_user(self, user_id):
    player = Player.all().filter('user_id =', user_id).get()    
    if not player:
        #This can result in duplicate players with the same user_id being created. 
        player = self.create_new_player(user_id)
        #This is what I'm trying to do. 
        #player = db.run_in_transaction(self.create_new_player, user_id=user_id)
    return player

  def create_new_player(self,user_id):
        #Check one more time for an existing user_id match.  
        player = Player.all().filter('user_id =', user_id).get()
        if player:
           return player

        player = Player()
        player.user_id = user.user_id()
        player.put()
        return player

【问题讨论】:

    标签: python google-app-engine


    【解决方案1】:

    使用用户名(或其他标识符)作为键名,并使用get_or_insert 以事务方式创建新实体或返回现有实体。 Sahid 的代码不起作用,因为没有事务,仍然可能出现竞争条件。

    【讨论】:

    • 谢谢尼克。我最初拥有的只是登录用户的 GAE 用户对象。你会推荐使用 user.user_id 作为键吗?
    • 是的,这对实体来说是一个很好的关键。
    • 还有一个问题,当我使用 get_or_insert 时,我得到的结果不是 id=1234567,而是 name=1234567890123456789。如何确保每个新实体都有一个 id=... 而不是 name=...?
    • 因为要执行 get_or_insert,您必须提供一个键名。否则,它无法确定是应该插入新实体还是返回现有实体。
    • 谢谢。我希望能够使用其中一个属性作为避免创建重复项的关键,但我仍然需要创建一个 ID 而不是名称,因为我已经在各个地方使用了 ID。
    【解决方案2】:

    也许你可以使用键名,get_by_key_name 比过滤器好。

     def create_new_player(self,user_id):
        key_name = "player/%s" % user_id
        player = Player.get_by_key_name (key_name)
        if player is None:
          player = Player (key_name=key_name, user_id=user_id)
          player.put ()
        return player
    

    随着尼克的最后评论,我更新了我的代码, 所以更好的解决方案是:

        def create_new_player(self,user_id):
          key_name = "player/%s" % user_id
          player = Player.get_or_insert (key_name=key_name, user_id=user_id)
          return player
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-25
      相关资源
      最近更新 更多