В приложении, которое имеет много «магазинов», каждый зарегистрированный пользователь-администратор имеет сущность «магазин», каждый магазин продает товары, в которых каждый товар относится к определенной « категории ». Наличие нескольких клиентов (в некоторых случаях по 100) каждый клиент имеет учетную запись для отслеживания своих покупок и прошлых заказов. Каждый магазин генерирует счета для своих клиентов, клиенты оплачивают счета.
Admin User -- > Shop
Shop ---> clients
|-> items Categories
|-> items
|-> invoices
|-> payments received
На странице администратора отображается отчет, показывающий счета в течение года (с января по декабрь), эта страница является требованием клиента. Магазин может вручную сгенерировать новый счет-фактуру при совершении покупки и записать платеж при его оплате. Примечание: все это происходит в реальном магазине, нет покупок через Интернет.
Поскольку один магазин генерирует несколько счетов в месяц (~ 100) и несколько платежей в месяц (~ 100), показ этой суммы в год легко дается тысячам организаций для отображения на одной странице.
Чтобы оптимизировать загрузку страницы и создание отчета о продажах за год (общий объем продаж, выручка, оплата и т. Д.), Мы решили структурировать данные таким образом, чтобы каждая категория товара в год также является юридическим лицом. Это означает, что всякий раз, когда совершается покупка для элемента в этой категории, нам нужно добавить цену покупки элемента к itemCategory в этом году в этом месяце.
itemCategory Модель:
itemCategory(ndb.Model):
shopID = ndb.KeyProperty()
year = ndb.IntegerProperty()
monthly_sales = ndb.FloatProperty(repeated=True) #12 months
Таким образом, мы можем загрузить всю таблицу продаж, прочитав только список itemCategory для этого магазина за этот год, вместо того, чтобы читать все отдельные покупки в течение года. Это позволит сэкономить большое количество операций чтения из хранилища данных и сократить время загрузки страницы за счет дополнительного чтения, суммирования и записи в эту сводку, например, сущности.
Category Jan Feb Mar ... Dec
--------------------------------------
Men's shoes 1000 1300 850 ... 1400
Kids shoes 600 850 650 ... 900
Сложность в этой точке заключается в том, что очень важна строгая согласованность для отдельных покупок и для сущностей itemCategory. Потому что, если магазин пытается добавить несколько покупок последовательно коротким временем, с возможной согласованностью itemCategory может еще не обновиться с последней суммой покупки. В результате неправильные значения продаж. Также то же самое для отдельной покупки, если было требование отредактировать одну сразу после ее добавления, запрос для объекта без его идентификатора может не иметь результатов. Таким образом, кажется, что запросы Ancestor здесь важны, возможно, магазин как родительский объект. Тем не менее, это приведет к конфликту позже (по крайней мере, до тех пор, пока Datastore не будет перенесен в Firestore), когда все эти сущности (в данном случае тысячи!) Имеют одного родителя!
То же самое касается счетов-фактур, генерация нового счета-фактуры означает знание последнего номера счета-фактуры, чтобы они всегда были в последовательности без пропусков. Запрос счета с возможной согласованностью может привести к дублированию номеров счетов.
Каков оптимальный способ структурирования данных на данном этапе для обеспечения строгой согласованности? К сожалению, проект был там в течение нескольких лет, и был начат с использованием Google Datastore, а не Cloud SQL (что кажется более подходящим для такого рода проектов). Надеемся, что все эти проблемы исчезнут после перехода на Firestore, который будет иметь строгую согласованность для всех операций чтения