Как установить фильтр для получения детей в определенный период времени с помощью eagerload_all () в SqlAlchemy - PullRequest
1 голос
/ 10 сентября 2010

У меня есть таблица сообщений , и в ней хранятся 3 типа сообщений: Тема , Ответ и Комментарий .У каждого есть родительский идентификатор.

# 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 Ответ

1 голос
/ 10 сентября 2010

Использование 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...