Google app engine ndb: put(), а затем query(), всегда есть один элемент

Интересно, столкнулся ли кто-нибудь с странной проблемой в 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. Тем не менее, length2 будет исправлено при повторном просмотре одной и той же страницы HTML позже. В чем проблема? Спасибо.

Ответ 1

Я решил это, выполнив соответствующий запрос, создав новую запись модели, а затем добавив его к моему запросу, прежде чем возвращать его. Изменив ваше, это выглядит так:

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)

В этом случае append_items имеет ваш запрос, плюс новый элемент. Генерация списка неэффективна, но я python/ndb noob и, вероятно, способ получить сборку прямо из модели Query, что было бы намного лучше.

Ответ 2

Это ожидаемое поведение; ваши запросы выше только в конечном итоге согласованы. То есть, вы не гарантируете получение самых последних результатов при запросе.

Вы можете обойти это, используя запрос предка (см. ссылку выше). Для вашего примера вам нужно предоставить каждому из своих элементов родительский объект, а затем использовать Item.query().ancestor(theParentEntity).fetch().

Ответ 3

Как сказал @JesseRusak, вам нужен предок Dummy для решения этой небольшой проблемы (у меня была та же проблема, что и вы недавно).

Но я не создал новую DummyEntity, а только DummyKey для DummyAncestor. Попробуйте это для вашей проблемы:

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 работал.

Ответ 4

Вы можете сослаться на их учебник по nbd здесь.
Они используют функцию для генерации ключа предка на основе некоторого свойства своей модели ndb. В зависимости от того, как вы хотите использовать свою базу данных, вы можете использовать свойство, уникальное для нескольких элементов, таких как свойство пользователя, в базе данных, в которой каждый пользователь имеет несколько сообщений. Или вы можете добавить новое свойство "фиктивный", скажем dummy = ndb.StringProperty(), и для каждого элемента инициализируйте этот макет с той же строкой, таким образом вы получите все записи, которые впоследствии могут быть отфильтрованы.

Ответ 5

Проблема, с которой вы столкнулись, заключается в том, что ndb предоставляет данные в конечном счете, состоящие. В результате, в конечном счете, для обновления данных обычно требуется ndb несколько секунд, чтобы вы могли использовать его позже. Это работает для большинства приложений, но если вам нужны данные сразу после отправки нового объекта, вам понадобятся данные сильно согласованные.

Google объясняет разницу в этой замечательной статье: https://cloud.google.com/appengine/docs/python/datastore/structuring_for_strong_consistency