是否可以在同一实体组中使用db模型和ndb模型?

时间:2012-11-09 19:38:18

标签: google-app-engine app-engine-ndb

我们有一个db模型Vote,我们已经使用了一段时间,最近添加了一个ndb模型Score,它代表实体的累积分数,基于其投票。目前Score是其投票的父级,因为我们希望它们都在同一个实体组中(因此可以在同一个事务中更新它们)。我一直在努力让一个可以更新VoteScore的交易,但它一直都会失败。这是一些示例代码:

    def transaction():
        score = self.key_score.get()
        vote = db.get(self.key_vote)

        # do stuff

        score.put()
        vote.put()
    db.run_in_transaction(transaction)

据我所知(仅限dev服务器),这总是重试四次:

WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
WARNING:root:Transaction collision. Retrying...
ERROR

然后我得到“TransactionFailedError:交易无法提交。请再试一次。”。

我已经尝试了一些方法来解决这个问题:

  1. 更改获取和放置的顺序 - 我想也许有一个实体组锁定问题,我不明白但是切换获取或放置的顺序并没有改变行为。< / p>

  2. 异步投放。这实际上就是我开始的 - 我知道同时放置db和ndb模型的唯一方法(我认为这实际上是在幕后放置多个键的原因)。结果相同。

    score_future = score.put_async()
    vote_future = db.put_async(vote)
    score_future.get_result()
    vote_future.get_result()
    
  3. db.run_in_transaction替换为ndb.transaction。这会引发“AttributeError:'Key'对象在db.get上没有属性'reference'”。我不确定这里发生了什么 - 看起来一些幕后代码正在db.Key预期ndb.Key

  4. 有趣的是,如果删除parent关系,我可以运行与上面相同的代码,这意味着实体不在同一个实体组中。

    那么,是否可以在同一个实体组中同时使用db和ndb模型?也许有一种简单的方法可以将db模型作为ndb,反之亦然?

1 个答案:

答案 0 :(得分:5)

所有实体与数据存储区看起来相同,无论它们是使用DB还是NDB创建的。这里的问题是你试图在API调用中混合两者; db在传递ndb模型实例时不知道该怎么做。

您需要创建一个与您的投票数据库模型相同的NDB模型 - 或者更好的是,将Vote迁移到NDB模型 - 并在需要两种实体类型的事务的任何代码中使用它。