0

我想了解如何ReferenceProperty用于常见的使用场景。
在典型的应用程序中,我们总是显示引用实体的列。

例如,考虑一个采购订单应用程序。

class POCategory(db.Model):
    name = db.StringProperty()

class POSubCategory(db.Model):
    category = db.ReferenceProperty(POCategory, collection_name='sub_categories')
    name = db.StringProperty()

class PurchaseOrder(db.Model):
    total_amount = db.FloatProperty()

class PurchaseOrderLineItem(db.Model):
    category = db.ReferenceProperty(POCategory, collection_name='po_line_items')
    sub_category = db.ReferenceProperty(POSubCategory, collection_name = 'po_line_items')
    amount = db.FloatProperty()

这是我们通常在典型应用程序中显示的内容。

+---------------+---------------+--------+
| 类别 | 子类别 | 金额 |
+---------------+---------------+--------+
| 蓝色类别 | 水 | $12.00 |
| 红色类别 | 火灾 | $20.00 |
+---------------+---------------+--------+
| 采购订单总计 | $22.00 |
+---------------+---------------+--------+

我应该为此使用ReferenceProperty Pre-fetching以避免 N+1 选择问题吗?

复制我的采购订单行项目中的类别和子类别名称,如下所示?

class PurchaseOrderLineItem(db.Model):
    category = db.ReferenceProperty(POCategory, collection_name='po_line_items')
    category_name = db.StringProperty()

    sub_category = db.ReferenceProperty(POSubCategory, collection_name = 'po_line_items')
    sub_category_name = db.StringProperty()

    amount = db.FloatProperty()

显然,类别和子类别的名称是可编辑的。
因此,当有人更新name属性时,我将不得不查询并遍历所有引用的PurchaseOrderLineItem实体并更新我的重复name属性。

    #----------------------------------------
    #             BAD DESIGN
    #----------------------------------------
    po_category.name = 'New Category Name'

    # build list of line items to be updated
    update_list = []
    for child_line_item in po_category.po_line_items:
        child_line_item.category_name = po_entity.name
        update_list.append(child_line_item)

    db.put(po_category, update_list)

我知道这不是一个很好的可扩展解决方案,因为随着时间的推移,我们将有很多 Line Items 需要更新。RDBMS 的思维方式很难摆脱。

那么有人可以教我如何思考这些典型场景吗?

谢谢!

4

1 回答 1

1

正如您所说,由于您经常可以编辑类别名称,因此您不应该将其嵌入到 Line Item 中。

而是使用 NDB(自动缓存获取)和 multi-get(一个 DB 调用来获取多个实体)来获取类别和子类别。

于 2013-04-26T09:39:04.170 回答