出于性能原因,我有一个非规范化数据库,其中一些表包含从其他表中的许多行聚合而来的数据。我想通过使用SQLAlchemy events来维护这个非规范化的数据缓存。例如,假设我正在编写论坛软件,并希望每个软件Thread
都有一个列来跟踪线程中所有评论的组合字数,以便有效地显示该信息:
class Thread(Base):
id = Column(UUID, primary_key=True, default=uuid.uuid4)
title = Column(UnicodeText(), nullable=False)
word_count = Column(Integer, nullable=False, default=0)
class Comment(Base):
id = Column(UUID, primary_key=True, default=uuid.uuid4)
thread_id = Column(UUID, ForeignKey('thread.id', ondelete='CASCADE'), nullable=False)
thread = relationship('Thread', backref='comments')
message = Column(UnicodeText(), nullable=False)
@property
def word_count(self):
return len(self.message.split())
所以每次插入评论时(为了简单起见,我们假设评论永远不会被编辑或删除),我们想要更新word_count
关联Thread
对象的属性。所以我想做类似的事情
def after_insert(mapper, connection, target):
thread = target.thread
thread.word_count = sum(c.word_count for c in thread.comments)
print("updated cached word count to", thread.word_count)
event.listen(Comment, "after_insert", after_insert)
因此,当我插入 a 时Comment
,我可以看到事件触发并看到它已正确计算字数,但该更改并未保存到Thread
数据库中的行中。我在after_insert 文档中没有看到有关更新其他表的任何警告,尽管我确实在其他一些表格中看到了一些警告,例如after_delete。
那么有没有支持的方式来使用 SQLAlchemy 事件呢?我已经将 SQLAlchemy 事件用于许多其他事情,所以我想以这种方式做所有事情,而不必编写数据库触发器。