在ndb.Transaction中生成和使用实体键

时间:2015-02-04 12:59:14

标签: google-app-engine transactions

我正在尝试从展示如何使用App Engine Search API的示例应用中了解this code snippet

rid = models.Review.allocate_ids(size=1)[0]
key = ndb.Key(models.Review._get_kind(), rid)

def _tx():
  review = models.Review(
      key=key,
      product_key=prod.key,
      username=username, rating=rating,
      comment=comment)
  review.put()
  # in a transactional task, update the parent product's average
  # rating to include this review's rating, and flag the review as
  # processed.
  defer(utils.updateAverageRating, key, _transactional=True)
  return review
return ndb.transaction(_tx)

所以基本上它会为产品创建一个Review实体,并添加一个延迟任务来更新该产品的平均评级。我有两个问题:

  1. 为什么这首先需要包含在交易中?如果它没有被放入交易中会出现什么问题?
  2. 为什么需要在交易之外生成Review实体密钥?在此示例之前,我甚至不知道allocate_ids()方法。这个更简单的替代方案也不会起作用吗?
  3. def _tx():
      review = models.Review(
          product_key=prod.key,
          username=username, rating=rating,
          comment=comment)
      review.put()
      # in a transactional task, update the parent product's average
      # rating to include this review's rating, and flag the review as
      # processed.
      defer(utils.updateAverageRating, review.key, _transactional=True)
      return review
    return ndb.transaction(_tx)
    

1 个答案:

答案 0 :(得分:1)

我也不明白。据我所知,绝对没有理由在交易之外手动分配密钥。 model.put()返回实体的密钥,您也可以从实例中获取它(就像您在示例中所做的那样)。如果put()是异步的,我可以看到逻辑(虽然我不会这样做),但事实并非如此。

这项交易似乎没有任何合理的理由。如果您只使用不依赖于已保留到数据存储区的数据的数据更新单个实体,则不需要事务。我能想到的唯一原因是确保仅在事务成功应用时才运行延迟任务,但由于没有真正的理由首先处理事务,您可以摆脱它并跳过添加延迟任务写操作失败。