如何在SqlAlchemy中通过eagerload_all()设置过滤器以在特定时间段内获取子项

时间:2010-09-10 03:17:37

标签: sqlalchemy

我有一个表帖子,它存储了3种类型的帖子,主题回复评论。每个人都有其父ID。

# Single table inheritance
class Post(Base):
    __tablename__ = 'posts'
    id = Column(Integer, primary_key=True)
    parent_id = Column(Integer, ForeignKey('posts.id'))
    discriminator = Column(String(1))
    content = Column(UnicodeText)
    added_at = Column(DateTime)
    __mapper_args__ = {'polymorphic_on': discriminator}

class Topic(Post):
    replies = relation("Reply")
    __mapper_args__ = {'polymorphic_identity': 't'}

class Reply(Post):
    comments = relation("Comment")
    __mapper_args__ = {'polymorphic_identity': 'r'}

class Comment(Post):
    __mapper_args__ = {'polymorphic_identity': 'c'}

我正在使用eagerload_all()来获取所有回复和评论属于一个主题:

session.query(Topic).options(eagerload_all('replies.comments')).get(topic_id)

我的问题是,如果我想在某个时间段(例如本周或本月)仅获得回复和回复评论。我该如何使用过滤器实现这一目标?

谢谢

1 个答案:

答案 0 :(得分:1)

使用eagerload_all只会在第一次请求children和/或Topic时立即查询对象Replies的{​​{1}},但是,因为您将Comments对象加载到会话中,所以它的所有相关子项也将被加载。这为您提供了第一个选择:

选项-1:在python代码中过滤而不是Topic
基本上在database对象上创建一个类似于

的方法
Topic

然后,您可以在class Topic(Post): ... def filter_replies(self, from_date, to_date): return [r for r in self.replies if r.added_at >= from_date and r.added_at <= to_date] 上执行类似的代码来过滤Replies或其中的任意组合。你明白了。

选项-2:在Comments级别上过滤:
为了实现此目的,您无需加载database对象,而是直接在Topic上过滤。以下查询会返回具有日期过滤器的给定Reply/Comment的所有Reply

Topic

由于您需要别名以便克服SQL语句生成问题,因为所有对象都映射到相同的表名称,因此注释的版本只需要更多一些:

topic_id = 1
from_date = date(2010, 9, 5)
to_date = date(2010, 9, 15)
q = session.query(Reply)
q = q.filter(Reply.parent_id == topic_id)
q = q.filter(Reply.added_at >= from_date)
q = q.filter(Reply.added_at <= to_date)
for r in q.all():
    print "Reply: ", r

显然,您可以创建一个将两个和平组合成更全面的查询的功能 要实现topic_id = 1 from_date = date(2010, 9, 5) to_date = date(2010, 9, 15) ralias = aliased(Reply) q = session.query(Comment) q = q.join((ralias, Comment.parent_id == ralias.id)) q = q.filter(ralias.parent_id == topic_id) q = q.filter(Comment.added_at >= from_date) q = q.filter(Comment.added_at <= to_date) for c in q: print "Comment: ", c this week类型的查询,您可以将这些过滤器转换为如上所示的日期范围,或使用SA的expression.func功能。