首页 > 解决方案 > sqlalchemy 在查询中过滤子项,但不是父项

问题描述

我有一个返回User对象的查询。Users 有许多Post他们制作的 s。当我执行查询时,我想User.post根据特定时间过滤找到的帖子。例如,仅返回给定时间戳 1 天内的帖子。

class User(base):
    __tablename__ = 'User'

class Post(base):
    __tablename__ = 'Post'

    user_id = Column(Integer, ForeignKey('User.uid'))
    user = relationship(User, backref=backref('post')
    time = Column(DateTime, default=func.current_timestamp())

有没有办法动态改变 orm 加载子项的方式,并在查询时指定?类似(伪代码):

User.query.filter_child(Post.time in timespan)

重要的是,如果没有符合条件的孩子,我不想过滤掉父母。我只想过滤给定用户的 orm 加载的子项。

标签: pythonsqlpostgresqlsqlalchemy

解决方案


加载自定义过滤集合是使用contains_eager(). 由于目标是加载所有User对象,即使它们没有Post与过滤条件匹配的对象,所以outerjoin()应该使用 an 并将帖子的谓词放在ONjoin 子句中:

end = datetime(2019, 4, 10, 12, 0)
start = end - timedelta(days=1)

# If you want to use half closed intervals, replace `between` with
# suitable relational comparisons.
User.query.\
    outerjoin(Post, and_(Post.user_id == User.uid,
                         Post.time.between(start, end))).\
    options(contains_eager(User.post))

推荐阅读