SQLAlchemy:如何查询自引用邻接列表表中的可选列?

时间:2016-10-14 22:12:54

标签: sqlalchemy cascading self-referencing-table

我有以下代表时间轴的Table模型。

class TimeRange(Base):


    __tablename__ = "time_line"


    record_id = Column(Integer, primary_key=True)
    level = Column(String, nullable=False) # e.g. "Point", "Range"
    content = Column(String, nullable=False)
    language_marker = Column(String) # this one column is optional and needs to be queried
    immediate_parent_id = Column(Integer, ForeignKey('time_line.record_id'))
    child_timelines = relationship('TimeRange', backref=backref('parent_timeline', remote_side=[record_id]))

language_marker列是需要以递归方式查询的列。并非所有记录都具有这样的属性,并且业务逻辑是:沿着从根到子时间轴的层次结构谱系,TimeRange实例的至少一个级别具有这样的属性,而最低级别的一个属性具有这样的属性。水平应该返回。这有点像级联样式表,如果TimeRange对象本身没有这样的属性,只需向上看一级,找到一个,最新定义的样式获胜。

我应该考虑实施此类查询的技术方向是什么?我使用的是SQLAlchemy,后端是SQLite。感谢。

1 个答案:

答案 0 :(得分:1)

我会添加一个以当前对象开头的属性derived_language_marker并上升到父TimeRange的层次结构,直到它找到一个不是None的language_marker并返回它:< / p>

 @property
 def derived_language_marker(self):
     time_range = self
     while not time_range.language_marker and time_range.parent_timeline:
         time_range = time_range.parent_timeline
     return time_range.language_marker

它可以像time_range.derived_language_marker一样访问,但缺点是如果父对象尚未加载,它可能会检查每个级别的SELECT查询。

(如果你为许多TimeRange执行此操作并且性能成为一个问题,只要最大可能的深度,就可以按照here所述的连接急切地将祖先加载到某个深度。并不是太极端。为了进一步优化,SQLite还有this approach。)