展平多态模型

时间:2018-08-14 19:41:38

标签: python sqlalchemy

我继承了库存管理系统。它使用python 3,flask和sqlalchemy。该系统包含零件和产品。产品具有物料清单(BOM)。 BOM由线组成,每条线可以是零件或另一产品。它们对嵌套产品的数量没有限制。 BOM行由下面的多态模型表示。

class ProductLine(db.Model):
    __tablename__ = 'ProductLineItems'

    id = db.Column('RowID', db.Integer, primary_key=True)
    product_id = db.Column('ProductID', db.Integer, db.ForeignKey(Product.id))
    qty = db.Column('ComponentQuantity', db.Float)
    is_subassembly = db.Column('IsSubAssembly', db.Boolean)

    product = db.relationship('Product', backref='bom_items', primaryjoin="(ProductLine.product_id==Product.id)")

    __mapper_args__ = {
        'polymorphic_on': is_subassembly,
    }


class ProductPart(ProductLine):
    __mapper_args__ = {'polymorphic_identity': False}
    part_id = db.Column('ComponentID', db.Integer, db.ForeignKey(Part.id))

    part = db.relationship('Part', backref='part_boms', primaryjoin="(ProductPart.part_id==Part.id)")

    @property
    def primary_vendor_cost(self):

    @property
    def alternate_vendor_cost(self):

    @property
    def is_subproduct(self):

    def contains_subproduct(self, subproduct):

    @validates('part_id')
    def validate_part_id(self, key, part_id):

class ProductSubproduct(ProductLine):
    __mapper_args__ = {'polymorphic_identity': True}

    subproduct_id = db.Column('SubAssemblyProductID', db.Integer, db.ForeignKey(Product.id))
    part = db.relationship('Product', backref='subproduct_boms',
                           primaryjoin="(ProductSubproduct.subproduct_id==Product.id)")

    @property
    def primary_vendor_cost(self):

    @property
    def alternate_vendor_cost(self):

    @property
    def is_subproduct(self):

    def contains_subproduct(self, subproduct):

    @validates('subproduct_id')
    def validate_subproduct_id(self, key, subproduct_id):

当前要查找产品中的所有零件,我正在使用python遍历每个BOM表行,并检查BOM表项是零件还是产品。如果是产品,那么我再次循环查找所有零件。

def flattened_bom(self, bom_dict, qty=1):        
    for item in self.bom_items:
        required_qty = item.qty * qty
        if item.is_subassembly:
            item.part.flattened_bom(qty=required_qty, bom_dict=bom_dict)
        else:
            empty_tuple = (item.part, 0)
            bom_dict[item.part.id] = (item.part, bom_dict.get(item.part.id, empty_tuple)[1] + required_qty)
    return bom_dict

这有效,但是速度很慢。我想知道他们是否是使用sqlalchemy orm或raw sql通过查询获得BOM表的所有部分的方法

1 个答案:

答案 0 :(得分:2)

我按照建议研究了递归CTE,并浏览了这两页,这有助于我进入下面的解决方案,该解决方案适用于Recursive CTE's ExplainedIBM Recursion Example

WITH cte_bom(ComponentID, ComponentQuantity, SubAssID) AS (
  SELECT Root.ComponentID, Root.ComponentQuantity, Root.SubAssemblyProductID
  FROM ProductLineItems AS Root
  WHERE Root.ProductID = ?
  UNION ALL
  SELECT Child.ComponentID, (Child.ComponentQuantity * Parent.ComponentQuantity), Child.SubAssemblyProductID
  FROM ProductLineItems AS Child, cte_bom AS Parent
  WHERE Parent.SubAssID = Child.ProductID

)
SELECT BOM.ComponentID, C.ComponentName, SUM(BOM.ComponentQuantity) AS Qty
FROM cte_bom AS BOM
INNER JOIN ComponentInventory C ON BOM.ComponentID = C.ComponentID
WHERE BOM.ComponentID NOT NULL
GROUP BY BOM.ComponentID