Использование eagerload_all
будет запрашивать только children
объекта Topic
немедленно, а не по первому запросу к Replies
и / или Comments
, но, поскольку вы загружаете объект Topic
всеанс, все связанные с ним дочерние элементы также будут загружены.Это дает вам первую опцию:
Опция-1: Фильтр в коде Python вместо 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
для фильтрации Comments
или любой их комбинации.Вы поняли.
Вариант-2: Фильтр на уровне database
:
Для этого вам не нужно загружать объект Topic
, а фильтровать напрямуюна Reply/Comment
.Следующий запрос возвращает все Reply
для данного Topic
с фильтром даты:
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
Версия для Комментария немного более сложна, так как вам требуется псевдоним для преодоления SQLПроблема генерации операторов, поскольку все ваши объекты сопоставлены с одним и тем же именем таблицы:
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
или this month
типа запросов вы можете либо преобразовать эти фильтры в диапазон дат, как показано выше, либо использовать функциональность expression.func в SA.