在具有多个“商店”的应用程序中,每个注册的管理员用户都有一个“商店”实体,每个商店出售商品,其中每个商品都属于某个“ 类别”。有多个客户(在某些情况下为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可能尚未更新为上一个购买金额。导致错误的销售价值。如果需要在购买后立即编辑一个,则对于个人购买也是如此,对没有其ID的实体的查询可能没有结果。因此,似乎在这里祖先查询是必不可少的,也许商店是父实体。但是,这将导致稍后(至少直到将数据存储区迁移到Firestore之前)所有这些实体(在这种情况下为数千个!)只有一个单亲的争用问题!
发票也一样,生成新发票意味着知道最新的发票号,以便它们始终无间断地排列。最终一致性查询发票可能会导致发票编号重复。
在这一点上构造数据以获得强一致性的最佳方法是什么?不幸的是,该项目已经存在了几年,并且开始使用Google Datastore而不是Cloud SQL(这似乎更适合此类项目)。希望所有这些问题在迁移到Firestore后都能消失,并且所有读取均具有强一致性