【问题标题】:sqlalchemy: "syncing" jsonb column between parent and child tablessqlalchemy:父表和子表之间的“同步”jsonb列
【发布时间】:2020-03-21 07:22:03
【问题描述】:

假设我们有两个SQLAlchemy的类 P>

from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.dialects.postgresql import JSONB


db = SQLAlchemy()

class Parent(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    data = db.Column(JSONB)

class Child(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    parent_id = db.Column(db.Integer, db.ForeignKey("parent.id"))
    parent = db.relationship(Parent, backref="children")
    data = db.Column(JSONB)

Child.data的含量是一个字典dParent.data的含量为辞典的列表,一个用于每个子,即parent.data = [child.data for child in parent.children] P>

有没有办法让两个data列同步? STRONG> P>


在一个原则上可以是例如摆脱Parent.data列,并与属性替换它简单地返回[child.data for child in parent.children]。然而,在我们使用的情况下,这是一个相当缓慢的,所以我们想保持聚合数据的一个副本Parent.data列。此外,应用程序的某些部分修改整个Parent.data一次,而其他修改Child.data。 我想过做data“私人”,写一个二传手,在其他表会自动更新相应的列(如果它更新一改之前,为了避免无限循环结束了,也许检查)。有没有更好的办法?

谢谢:)

【问题讨论】:

    标签: python database postgresql sqlalchemy flask-sqlalchemy


    【解决方案1】:

    您可能想要使用事件侦听器。像下面这样的东西应该这样做,这取决于你的 json 的结构

    import sqlalchemy as sa
    @sa.event.listens_for(Parent.data, "modified")
    def _parent_data_modified(parent, data, initiator):
        for child in parent.children:
            # adjust for your data structure
            child.data = data[child.id]
    
    @sa.event.listens_for(Child.data, "modified")
    def _child_data_modified(child, data, initiator):
        old_data = parent.data.copy()
        old_data[child.id] = data
        parent.data = old_data
    

    https://docs.sqlalchemy.org/en/13/orm/extensions/mutable.html#receiving-events

    【讨论】:

    • 嘿,谢谢你的回答!我稍后会尝试实现它并让你知道。只有一个问题,如果我修改说Child,那么_child_data_modified 将被调用并修改Parent。这不会导致_parent_data_modified 修改Child,导致无限循环吗?或者侦听器是否真的检查数据是否已被更改?
    • 好问题!我认为您应该能够在listens_for once=True 中指定以防止它多次触发。见docs.sqlalchemy.org/en/13/core/…
    猜你喜欢
    • 2019-06-17
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 2012-10-06
    • 2019-12-20
    • 1970-01-01
    • 2020-06-18
    • 1970-01-01
    相关资源
    最近更新 更多