【问题标题】:Modelling many-to-many with relation data in Google App Engine在 Google App Engine 中使用关系数据建模多对多
【发布时间】:2011-08-11 12:54:35
【问题描述】:

我的应用程序中有两个模型,Transaction 和 Person,具有多对多关系。每笔交易都包括一些人。对于每个人,该人所连接的每笔交易也有一个金额。因此,我需要用关系数据建模多对多关系。 Google 建议采用这种方法:

http://code.google.com/intl/sv-SE/appengine/articles/modeling.html

通过这种方法,我有一个这样的模型:

class TransactionPerson(db.Model):
    # References
    transaction = db.ReferenceProperty(Transaction, required=True)
    person = db.ReferenceProperty(Person, required=True)
    # Values
    amount = db.FloatProperty(required=True)

但我发现这对性能非常不利,因为如果我需要汇总所有交易中每个人的金额,我需要循环 Person*Transaction*TransactionPerson 次以在汇总金额时实现“加入”。

我的想法

我的想法是在 Transaction 模型中有两个列表:

class Transaction(db.Model):
    persons = ListProperty(db.Key)
    persons_amount = ListProperty(float)

这样我就不需要遍历每个人的所有 TransactionPerson 来找到关联的 Transaction。而且我仍然可以根据 Person 查询 Transactions。

问题

  1. 这可能吗?您能否相信在存储/检索时列表顺序始终相同,以便列表之间的索引同步?
  2. 这是实现与关联数据的多对多关系的好方法吗?

【问题讨论】:

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


    【解决方案1】:

    我怀疑你解决了错误的问题。中间关联实体是一个很好的方法。您遇到的问题是摘要需要很长时间来计算;你应该更关心这一点;

    首选方法是提前计算汇总数据

    在“每个人的交易总数”的特定情况下,这意味着您希望向 Person 模型添加一个额外的字段,并使用他们所有交易的运行总数来更新它。您将在任何时候修改 TransactionPerson 时更新它,以便汇总值始终正确。

    【讨论】:

    • 但是为什么中间关联实体会导致操作效率降低时是一种好方法?例如用你的方法;如果更新了事务,我经常需要更新与事务关联的所有 Person 对象。如果我使用我的方法,我不需要那个?使用关联实体更好的原因是什么?
    • 对于您正在做的事情,两者都可能是更好的选择,但我的回答集中在计算汇总数据的具体问题上。如果您必须加载多个实体来满足特定请求,您可能需要找到一种方法从请求中提取该过程并以其他方式构建它,例如值何时发生变化。跨度>
    • 汇总数据只是一个例子。我经常希望让所有人参与事务,这实际上会导致相同的 PersonTransactionTransactionPerson 循环,即使我做得更多,不会在性能方面是可以接受的很少见(当我添加或编辑 TransactionPerson 时)。即使我应该在事务中缓存该数据(人员列表),这与我在问题中建议的内容相同,但还会在列表中添加关系数据。它不会导致重复的数据。你会怎么做?
    • 在写入时进行汇总是个好主意,但反规范化也是如此,就像 OP 在第二个示例中所做的那样。
    【解决方案2】:

    1. 是的,您可以依赖正在维护的订单。来自docs

    当查询和 get() 返回实体时,列表属性值的顺序与存储时的顺序相同。有一个例外:Blob 和 Text 值被移到列表的末尾;但是,它们彼此之间保持原来的顺序。

    2. 是的,ListProperties 是反规范化关系的朋友。我倾向于大量复制数据,并以这种方式使用非规范化数据的“缓存”等列表属性。

    【讨论】:

    • 关于(2),复制数据是什么意思?就我而言,这不是重复,只是存储关系数据的一种方式?
    • 有时我会保持标准化设置,A has many B,但每当我保存B's 时,我也会在A 的列表中缓存一些重要数据,以便以后更快地处理。跨度>
    猜你喜欢
    • 2010-12-17
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-17
    • 2016-09-19
    • 1970-01-01
    相关资源
    最近更新 更多