0

У меня есть Ndb модели:NDB Фильтрация Структурированные собственности Google App Engine

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 объекта.

Когда я вижу эту сумку, я могу просто обновить (имя-проекта обновление имя-проекта appcfg.py -A питон), и это работает ...

Любые идеи, что я делаю неправильно или как это исправить?

+1

Я предполагаю, что это связано с возможной последовательностью. https://cloud.google.com/datastore/docs/concepts/structuring_for_strong_consistency –

ответ

1

Это очень вероятно Eventual Consistency. Когда вы разрабатываете свою систему с помощью Cloud Datastore, вам необходимо запланировать случай, когда эти запросы могут занять некоторое время, чтобы стать актуальными. Вероятно, перераспределение вашего приложения в этом случае занимает достаточно времени, чтобы информация обновлялась к моменту проверки.

Чтобы гарантировать сильную согласованность, вы хотите упорядочить свои данные в Entity Groups. Важное соображение для вашей модели данных заключается в том, что внутри EG вы можете запросить строго согласованный подход. Тем не менее, вы можете обновлять только одну группу сущностей с постоянной скоростью 1 обновление в секунду (это обновление может быть пакетным обновлением, хотя).

Постарайтесь выровнять эти группы объектов по естественным границам, чтобы ограничить скорость, с которой любая группа сущностей будет записана в качестве шкалы приложений. Например, у вас может быть одна группа объектов для каждого пользователя или в случае вашего приложения, возможно, одна группа объектов в Shop. Если вы поместите все Product s для одного Shop в одну группу сущностей, вы всегда можете перечислить все Product s в магазине строго согласованным образом. Вы не смогли бы увеличить количество людей, добавляющих предметы в магазин (вы ограничены записью продуктов в магазин на одну партию в секунду), но это, вероятно, будет приемлемым ограничением для системы.

Так, учитывая следующую раскладку вместо:

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 в качестве кода.Тогда вам не придется выдавать запрос для этого:

ProductInShop(id=product.code, product=product, price=10.0).put() 

Затем, вы можете поиска ваш ProductInShop без необходимости выдавать запрос с:

product_in_shop = ndb.Key(Shop, request.shop_key, ProductInShop, request.code).get() 
Смежные вопросы