我正在编写一个基于事件溯源和 CQRS 原则的应用程序。该应用程序基本上是一个“交易跟踪器”,为了举例说明这个问题,我们可以认为每个
Transaction
都链接到一个 Asset
.
class Asset(models.Model):
code = models.CharField(...)
current_price = models.DecimalField(...)
sector = models.CharField(...)
...
def get_roi(self, percentage: bool = False) -> Decimal:
# Expensive calculation using several joins in multiple tables
return self.transactions.roi(incomes=self.incomes.sum(), percentage=percentage)["ROI"]
class Transaction(models.Model):
asset = models.ForeignKey(to=Asset, on_delete=models.CASCADE, related_name="transactions")
...
class Income(models.Model):
asset = models.ForeignKey(to=Asset, on_delete=models.CASCADE, related_name="incomes")
...
我的资产列表端点有几个字段,在规范化数据库中计算成本很高。如果出现以下情况,这些字段会发生变化:
Transaction
被创建或删除Income
被创建或删除current_price
变化为了扩展以及出于您可能已经知道的其他几个原因,我想将那些计算成本高的字段与写入模型分开。 我的疑问源于这样一个事实,即读取模型必须具有一些可能永远不会改变并且与上述事件无关的字段。
例如,我有一份报告汇总了每个
ROI
的 sector
s。对于读取模型,我必须有一个 sector
字段来生成此报告。如果是这样,每次 sector
更改时我也必须同步读取模型。
因为我有几个这样的字段,所以如果给定的写入Asset
被触摸(创建,更新或删除),也更容易触发读取模型更新。这对我来说既奇怪又有点矫枉过正。这种想法的主要原因是更改“报告字段”与Asset
聚合域及其业务规则无关。
话虽如此,我想到的一种替代方法是简单地使用非规范化字段扩展写入模型。这样做除了对我来说看起来很奇怪之外还会引发一些危险信号。
你认为这里最好的方法是什么?