【问题标题】:Many to Many Relationship in a Transactional System With Google Datastore/Python NDB使用 Google Datastore/Python NDB 的事务系统中的多对多关系
【发布时间】:2014-10-20 08:57:20
【问题描述】:

我正在为一家农作物仓储公司编写申请,该公司购买收获的农作物并将其存储在一个或多个仓库中。到目前为止,Google App Engine/Datastore 的限制并没有给我带来问题。而且我对这个项目的投入如此之深,以至于很难返回。

我必须在两个 种类 之间建立多对多关系,它们本质上是事务性的(意味着父/祖先查询)。我不确定这样做的正确方法是什么。这是业务逻辑:

  1. 仓库为特定数量 (PO) 发出采购订单。因此,我们为每个采购订单 (PO) 在 PO 种类 中创建一个实体。

  2. 仓库收到货物。所以我们在GRN Kind中创建了一个实体。 (GRN=收货单)。

这是多对多的关系。

  1. 可能需要一个 GRN 才能完成一份 PO。

  2. 可能需要一个 GRN 才能完成许多 PO。

  3. 可能需要许多 GRN 才能完成一份 PO。

  4. 可能需要许多 GRN 才能完成许多 PO。

这是代码的相关快照。

class Warehouse(ndb.Models):
    name = ndb.TextProperty()
    capacity = ndb.FloatProperty()
    current_stock = ndb.FloatProperty()

class PurchaseOrder(ndb.Models):
    quantity = ndb.FloatProperty()
    remaining = ndb.FloatProperty()
    is_complete = ndb.BooleanProperty()
    grn = ndb.KeyProprty(repeated=True, kind=GRN)

class GRN(ndb.Models):
    quantity = ndb.FloatProperty()
    remaining = ndb.FloatProperty()
    is_complete = ndb.BooleanProperty()
    po = ndb.KeyProprty(repeated=True, kind=PurchaseOrder)

实体组关系

仓库 -> GRN

仓库 -> 采购订单

为了建立多对多关系,我将所有相关的 GRN 密钥保存在 PO 记录中,并将所有相关的 PO 密钥保存在 GRN 记录中。这对我来说很好。

但如果我必须在回溯日期编辑 GRN 或 PO,那么我无法处理可能影响其他 GRN 和 PO 的级联更改的复杂性。

  • 在我读到的某处,我应该使用第三种模型来保存多对多关系,而不是存储相关的键。我无法想象第三个表应该包含什么。 *

我知道我的问题非常具体,我还没有完成所有细节。但是,请帮助我针对这种问题模式采取正确的方法。我会处理剩下的。或者提供任何链接,如果这已经记录在某处。

【问题讨论】:

  • 您是否应该在 PO 和 GRN 之间保持数量等属性同步?
  • 是的,两者都需要平衡重量。
  • 假设一个PO由100KG组成,那么它可以链接到5个20KG的GRN实例。只有当 PO 和 GRN 之间的多对多关系通过权重平衡时,才认为 PO 和 GRN 是完整的。
  • 那么,看起来每个相关的 GRN 和 PO 都属于一个实体组,为什么不使用 ComputedProperty 来获取所有相关实体并检查权重?

标签: google-app-engine app-engine-ndb google-cloud-datastore


【解决方案1】:

我会添加一个名为 GRNinstance 的多对多关系,它将单个 GRN 实例与单个 PO 链接起来:

class PurchaseOrder(ndb.Models):
    quantity = ndb.FloatProperty()
    remaining = ndb.FloatProperty()
    is_complete = ndb.BooleanProperty()

class GRN(ndb.Models):
    quantity = ndb.FloatProperty()
    remaining = ndb.FloatProperty()
    is_complete = ndb.BooleanProperty()

class GRNinstance(ndb.Models):
    po = ndb.KeyProperty(kind=PurchaseOrder)
    grn = ndb.KeyProperty(kind=GRN)
    quantity = ndb.FloatProperty()

特定poGRNinstance.quantity 总和应为PurchaseOrder.quantity,特定grnGRNinstance.quantity 总和应为GRN.quantity

事实上,Dmitry 的ComputedProperty 可以同时替换PurchaseOrder.quantityGRN.quantity(但这可能会很慢)。也许is_complete 可以是一个简单的测试:

is_complete = ndb.ComputedProperty(lambda self: self.remaining > 0)

【讨论】:

  • 太棒了!实际上我采取了类似的方法,使用第三个表来建立两个 Kinds 之间的关系。非常感谢,您的回答让我有信心走在正确的轨道上。
猜你喜欢
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
  • 2016-09-19
  • 2010-11-10
  • 1970-01-01
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多