在Google App Engine中,如何避免创建具有相同属性的重复实体?

3 投票
2 回答
1509 浏览
提问于 2025-04-16 03:44

我正在尝试添加一个事务,以防止创建两个具有相同属性的实体。在我的应用中,每当我看到一个新的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

2 个回答

1

也许你可以使用键名,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

根据Nick的最后一条评论,我更新了我的代码,所以更好的解决方案是:

    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
4

使用用户名(或者其他标识符)作为键名,然后用 get_or_insert 方法来安全地创建一个新实体,或者返回已经存在的那个。Sahid 的代码是行不通的,因为如果没有事务处理,还是有可能出现竞争条件。

撰写回答