谷歌应用引擎ndb:put()然后查询(),总有一个项目

时间:2013-03-17 12:52:58

标签: google-app-engine

我想知道是否有人在Google App Engine的NDB上遇到了这个奇怪的问题:在创建新实体并通过put()保存之后;然后立即query(),总有一个项目。例如,

class Item(ndb.Model):
    ...
    ...

items = Item.query().fetch()
length1 = len(items)
item = Item()
item.put()
items = Item.query().fetch()
length2 = len(items)

在上文中,length1始终等于length2。但是,稍后重新访问同一HTML页面时,将更正length2。问题是什么?感谢。

5 个答案:

答案 0 :(得分:21)

这是预期的行为;您上面的查询是only eventually consistent。也就是说,查询时无法保证获得最新结果。

您可以使用祖先查询来解决此问题(请参阅上面的链接)。对于您的示例,您需要为每个项目提供父实体,然后使用Item.query().ancestor(theParentEntity).fetch()

答案 1 :(得分:8)

正如@JesseRusak所说,你需要一个虚拟的祖先来解决这个小问题(我最近遇到了同样的问题)。

但我没有制作新的DummyEntity,只是DummyAncestor的DummyKey。试试这个问题:

class Item(ndb.Model): ... ... items = Item.query(ancestor=ndb.Key(Item, 'Items')).fetch() length1 = len(items) item = Item(parent=ndb.Key(Item, 'Items')) item.put() items = Item.query(ancestor=ndb.Key(Item, 'Items')).fetch() length2 = len(items)

至少在我的情况下,DummyAncestor工作了。

答案 2 :(得分:1)

您可以参考他们关于nbd here的教程 它们使用函数根据其ndb模型的某些属性生成祖先密钥。 根据您对数据库的需求,您可以在数据库中使用对于多个项目(例如User属性)唯一的属性,其中每个用户都有几个帖子说。或者你可以添加一个新的虚拟属性,比如说dummy = ndb.StringProperty(),并且每个项目使用相同的字符串初始化那个虚拟对象,这样你就可以得到以后可以过滤的所有条目。

答案 3 :(得分:1)

您遇到的问题是ndb提供" 最终一致"数据。通过最终一致的数据,通常需要ndb几秒钟来更新数据,以便您以后可以使用它。这适用于大多数应用程序,但如果您在提交新实体后立即需要数据,则需要" 强烈一致"数据。

谷歌解释了这篇伟大文章的不同之处: https://cloud.google.com/appengine/docs/python/datastore/structuring_for_strong_consistency

答案 4 :(得分:-3)

我通过进行适当的查询,创建新的模型记录,然后在返回之前将其附加到我的查询中来解决这个问题。修改你的,看起来像:

class Item(ndb.Model):
    ...
    ...

items = Item.query().fetch()
length1 = len(items)
item = Item()
item.put()

appended_items = list()
for existing_item in items:
    appended_items.append(existing_item)

appended_items.append(item)
length2 = len(appendeditems)

在这种情况下,attached_items包含您的查询以及新元素。列表生成是低效的,但我是一个python / ndb noob,并且可能有一种方法可以将Collection从Query模型中拿出来,这样会好得多。