我有ndb模型:
class Product(ndb.Model):
name = ndb.StringProperty()
description = ndb.StringProperty()
code = ndb.StringProperty()
class Category(ndb.Model):
name = ndb.StringProperty()
class Shop(ndb.Model):
name = ndb.StringProperty()
category = ndb.StructuredProperty(Category)
address = ndb.StringProperty()
class ProductInShop(ndb.Model):
product = ndb.StructuredProperty(Product)
shop = ndb.StructuredProperty(Shop)
price = ndb.FloatProperty()
在一个功能中,我需要在商店中找到产品(产品代码和商店密钥请求)。如果店内没有产品(返回无),那么我需要创建它。 如果存在则从请求更新价格值。现在我正在通过gql进行查询。
product_in_shop = ndb.gql(
'SELECT * FROM ProductInShop WHERE \
product.code = :1 AND shop = :2 LIMIT 1',
request.code,
ndb.Key(Shop, request.shop_key).get()
).get()
它工作正常。
但!有些时候product_in_shop = None
应该有一个实体(我在数据库中检查过)。
我试图进行另一个查询以计算实体,它返回0,但是有超过1个实体。
当我看到这个包时,我可以更新(python appcfg.py -A project-name update project-name)并且它可以工作......
任何想法我做错了什么或如何解决它?
答案 0 :(得分:1)
这很可能Eventual Consistency。使用Cloud Datastore设计系统时,需要规划这些查询需要时间才能变为最新的情况。可能,在这种情况下重新部署您的应用程序只需要足够的时间,以便在您再次检查时更新信息。
为了保证一致性,您需要将数据整理到实体组中。数据模型的一个重要考虑因素是,在EG中,您可以以一致的方式进行查询。但是,您只能以每秒1次更新的持续速率更新单个实体组(但此更新可能是批量更新)。
尝试沿自然边界对齐这些实体组,以帮助限制在应用程序扩展时将写入任何给定实体组的速率。例如,每个用户可能只有一个实体组,或者对于您的应用程序,每个Shop
可能只有一个实体组。如果您将单个Product
的所有Shop
放入一个实体组中,则始终可以以强烈一致的方式列出商店中的所有Product
。您无法扩大向商店添加商品的人数(您只能将商品写入商店每秒一批),但这可能是系统可接受的约束条件。
因此,请考虑以下布局:
class Product(ndb.Model):
name = ndb.StringProperty()
description = ndb.StringProperty()
code = ndb.StringProperty()
class Category(ndb.Model):
name = ndb.StringProperty()
class Shop(ndb.Model):
name = ndb.StringProperty()
category = ndb.StructuredProperty(Category)
address = ndb.StringProperty()
class ProductInShop(ndb.Model):
product = ndb.StructuredProperty(Product)
price = ndb.FloatProperty()
当您创建ProductInShop
时,您希望将父级设置为其所属的Shop
的键。例如:
ProductInShop(parent=ndb.Key(Shop, request.shop_key),
product=Product(...), price=10.0).put()
然后,您可以使用特定代码为给定商店中的一个产品发出查询:
product_in_shop = ndb.gql(
'SELECT * FROM ProductInShop WHERE \
product.code = :1 AND ANCESTOR IS :2 LIMIT 1',
request.code,
ndb.Key(Shop, request.shop_key)
).get()
作为旁注,如果您的code
对于单个产品是唯一的,请考虑将ProductInShop
的ID设置为代码。然后,您不必为此发出查询:
ProductInShop(id=product.code, product=product, price=10.0).put()
然后,您可以查找ProductInShop
,而无需使用以下方式发出查询:
product_in_shop = ndb.Key(Shop, request.shop_key, ProductInShop, request.code).get()