【问题标题】:sqlalchemy filter children in query, but not parentsqlalchemy 在查询中过滤子项,但不是父项
【发布时间】:2019-04-10 18:03:34
【问题描述】:

我有一个返回 User 对象的查询。 Users 有很多 Posts 是他们制作的。当我执行查询时,我想根据特定时间过滤在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 加载的子项。

【问题讨论】:

  • 相关,如果不是 stackoverflow.com/questions/21924347/… 的副本。唯一的区别是使用outerjoin 而不是join
  • 相关,但您的链接涉及根据子属性过滤父级。就我的问题而言,我不希望根据子属性过滤父级,只希望通过给定属性限制在父级中加载的子级。
  • 我实际上尝试了 outerjoinfilter 但结果是当没有匹配过滤器的帖子时我没有返回任何用户对象。

标签: python sql postgresql sqlalchemy


【解决方案1】:

Loading custom filtered collections 使用 contains_eager() 完成。由于目标是加载所有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))

【讨论】:

    【解决方案2】:

    我不确定这就是你要找的东西,但是这种 KISS 方法有什么问题?

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

    【讨论】:

    • 这将返回一组Post 对象。我想检索User 对象,但我希望它们嵌入的Post 集合(User.post)具有一组按某些条件(时间戳)过滤的对象。
    • 啊,明白了。你想要这个的实际情况是什么?我可以想象还有其他方法可以实现您的目标(尽管从技术角度来看这是一个有趣的问题)
    • 创建计算高效的方法来检索信息。检索数据然后更改其数据结构通常比直接检索您需要的数据结构效率低
    猜你喜欢
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 2020-11-14
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 2018-03-18
    相关资源
    最近更新 更多