Google App Engine 数据存储建模问题

Google App Engine Datastore modeling issue

从传统关系数据库迁移到非关系数据库(例如 App Engine 数据存储)时,关于如何正确进行数据建模的问题数不胜数。

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

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

实现如下:

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 class 中的 Vendor 属性 只是一个 Key 而不是对象本身。所以 JINJA 无法理解表达式 {{expense.vendor.friendlyName}}

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

另一种方法是使用 StructuredProperty 而不是 KeyPrperty。但是,一个解决方案要求是能够重命名供应商友好的名称,这应该会影响所有现有费用。在每个结构化 属性 之后寻找变化是很疯狂的。

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

感谢您对此的支持。

在您的模板中,您可以执行以下操作:

{{ 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)