在使用没有键名的祖先关系时,我在确保我的数据正确的 Google App Engine 中遇到了一些麻烦。
让我再解释一下:我有一个父实体category,我想创建一个子实体item。我想创建一个接受类别名称和项目名称的函数,如果它们不存在,则创建这两个实体。最初,我创建了一个事务,并在需要时使用键名在事务中创建了两个事务,这很好用。但是,我意识到我不想使用名称作为键,因为它可能需要更改,我尝试在我的事务中执行此操作:
def add_item_txn(category_name, item_name):
category_query = db.GqlQuery("SELECT * FROM Category WHERE name=:category_name", category_name=category_name)
category = category_query.get()
if not category:
category = Category(name=category_name, count=0)
item_query = db.GqlQuery("SELECT * FROM Item WHERE name=:name AND ANCESTOR IS :category", name=item_name, category=category)
item_results = item_query.fetch(1)
if len(item_results) == 0:
item = Item(parent=category, name=name)
db.run_in_transaction(add_item_txn, "foo", "bar")
当我尝试运行它时,我发现 App Engine 拒绝了它,因为它不允许您在事务中运行查询:Only ancestor queries are allowed inside transactions
.
看看谷歌给出的关于如何解决这个问题的例子:
def decrement(key, amount=1):
counter = db.get(key)
counter.count -= amount
if counter.count < 0: # don't let the counter go negative
raise db.Rollback()
db.put(counter)
q = db.GqlQuery("SELECT * FROM Counter WHERE name = :1", "foo")
counter = q.get()
db.run_in_transaction(decrement, counter.key(), amount=5)
我试图将获取的类别移到交易之前:
def add_item_txn(category_key, item_name):
category = category_key.get()
item_query = db.GqlQuery("SELECT * FROM Item WHERE name=:name AND ANCESTOR IS :category", name=item_name, category=category)
item_results = item_query.fetch(1)
if len(item_results) == 0:
item = Item(parent=category, name=name)
category_query = db.GqlQuery("SELECT * FROM Category WHERE name=:category_name", category_name="foo")
category = category_query.get()
if not category:
category = Category(name=category_name, count=0)
db.run_in_transaction(add_item_txn, category.key(), "bar")
这似乎可行,但我发现当我使用一些创建了重复类别的请求运行它时,这是有道理的,因为该类别是在事务之外查询的,并且多个请求可以创建多个类别。
有谁知道如何正确创建这些类别?我试图将类别创建放入事务中,但仅再次收到有关祖先查询的错误。
谢谢!
西蒙