【问题标题】:Google App Engine Datastore modeling issueGoogle App Engine Datastore 建模问题
【发布时间】:2015-10-08 20:52:47
【问题描述】:

在从传统关系数据库迁移到非关系数据库(如 App Engine Datastore)时,如何正确地进行数据建模存在大量问题。

NDB官方文档看了很多遍,网上也试了几个教程,还是卡住了。

我正在开发一个记录我所有个人开支的财务应用程序。这意味着我设计了一个名为 Expense 的实体,上面有一些属性。作为费用的一部分,我还设计了一个供应商实体来存储与商家相关的信息。

这里是实现:

class Expense(ndb.Model):
    amount = ndb.FloatProperty(required=False)
    description = ndb.StringProperty()
    vendor = ndb.KeyProperty(kind=Vendor)

class Vendor(ndb.Model):
    companyName = ndb.StringProperty(required=False)
    friendlyName = ndb.StringProperty(required=False, default="")

这是检索费用信息的代码:

def get(self):
    template_page = "expense.html"
    template_values = {'expense':Expense.query()}

    self.renderTemplatePage(template_page, template_values)

我在上面的设计中面临的问题是如何检索费用和供应商信息并将其传递给 JINJA 进行渲染。正如我所料,Expense 类中的 Vendor 属性只是一个 Key 而不是对象本身。所以 JINJA 无法理解表达式 {{expense.vendor.friendlyName}}

虽然问题似乎是技术问题,但我相信我的困难与非关系数据库的概念以及我应用于解决方案的类似传统的设计有关。

另一种方法是使用 StructuredProperty 而不是 KeyPrperty。但是,一个解决方案要求是能够重命名供应商友好名称,这将影响所有现有费用。跟踪每个结构化属性并找到更改是很疯狂的。

在放弃 App Engine 并转向 Google Cloud SQL 之前,我想听听一些关于如何解决这种数据建模场景的建议。也许我需要构建的解决方案不推荐用于非关系数据库。

感谢您对此的任何支持。

【问题讨论】:

    标签: python google-app-engine google-cloud-datastore data-modeling app-engine-ndb


    【解决方案1】:

    在你的模板中你可以这样做:

    {{ expense.vendor.get().friendlyName }}
    

    或者你可以为你的模型添加一个属性:

    class Expense(ndb.Model):
        amount = ndb.FloatProperty(required=False)
        description = ndb.StringProperty()
        vendor = ndb.KeyProperty(kind=Vendor)
    
        @property
        def vendor_name(self):
          return self.vendor.get().friendlyName
    

    这将允许在您的模板中:

    {{ expense.vendor_name }}
    

    为了避免这种效率如此低下,您可以在显示费用列表之前获取供应商,在循环内调用 get 只是本地内存查找:

    def get(self):
        template_page = "expense.html"
        expenses = Expense.query().fetch()
        ndb.get_multi([e.vendor for e in expenses])
        template_values = {'expense':expenses}
    
        self.renderTemplatePage(template_page, template_values)
    

    【讨论】:

    • 感谢您的帮助,格雷格。非常感激!两种方法都工作得很好。现在,就设计而言,这真的应该是这样吗?我将向 Expense 实体添加更多 KeyProperty,例如类别和付款。我仍然需要改变我对非关系数据库数据建模的心态。我不清楚何时选择一种或另一种数据库技术。
    • @FabioMoggi 讨论与 ndb 的关系:stackoverflow.com/q/14739044/584846
    • 感谢@BrentWashburne 的提示
    • @Greg 我不相信最终的“优化”sn-p。执行ndb.get_multi([e.vendor for e in expenses]) 确实会获得与费用对应的所有供应商实体,但不会以任何方式保留它们,因此只会增加实体在缓存中的可能性。如果您要进行一些 pre-jinja2 Python 处理,那么您最好将e.vendor.get() 的结果附加到每笔费用中,例如for e in expenses: e._vendor = e.vendor.get()
    • @patb 如果我的说服力不够,也许可以阅读文档?:cloud.google.com/appengine/docs/python/ndb/cache#incontext
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-09
    • 2014-05-29
    • 2013-08-11
    • 1970-01-01
    • 2014-03-12
    • 2012-07-09
    相关资源
    最近更新 更多