简体   繁体   English

sqlalchemy筛选查询中的子级,但不是父级

[英]sqlalchemy filter children in query, but not parent

I have a query which returns a User object. 我有一个查询,返回一个User对象。 User s have a number of Post s which they have made. User拥有许多已Post When I perform a query, I want to filter the posts found in User.post based on a specific time. 执行查询时,我想根据特定时间过滤User.post找到的帖子。 For example, to return only the posts within 1 day of a given timestamp. 例如,仅返回给定时间戳记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())

Is there a way to dynamically change the way the children are loaded by the orm, and to specify that at query time? 有没有一种方法可以动态更改orm加载子级的方式,并在查询时进行指定? Something like (pseudocode): 类似于(伪代码):

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

Importantly, I don't want to filter out parents if there are no children which match the criteria. 重要的是,如果没有符合条件的孩子,我不想过滤掉父母。 I only want to filter the children loaded by the orm for the given Users. 我只想过滤orm为给定用户加载的子级。

Loading custom filtered collections is done using contains_eager() . 使用contains_eager()完成加载自定义过滤的集合 Since the goal is to load all User objects even if they have no Post objects that match the filtering criteria, an outerjoin() should be used and the predicates for posts put in the ON clause of the join: 因为目标是即使所有User对象都没有符合过滤条件的Post对象,也要加载它们,所以应该使用outerjoin() ,并将谓词的谓词放在连接的ON子句中:

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))

I'm not sure this is what you are looking for, but what's wrong with this KISS approach? 我不确定这是您要寻找的东西,但是这种KISS方法有什么问题呢?

Post.query.filter(Post.user == <username>).filter(
    Post.time > START_OF_DAY).filter(Post.time < END_OF_DAY).all()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM