class Post(Base):
__tablename__ = 'posts'
id = Column(BigInteger, primary_key=True, autoincrement=True)
names = relationship('PostTranslation', backref='posts')
tags = relationship('PostTag', backref='posts')
class Language(Base):
__tablename__ = 'languages'
id = Column(BigInteger, primary_key=True, autoincrement=True)
lang = Column(Unicode(255), nullable=False)
class Tag(Base):
__tablename__ = 'tags'
id = Column(BigInteger, primary_key=True, autoincrement=True)
name = Column(Unicode(255), nullable=False)
class PostTranslation(Base):
__tablename__ = 'post_translation'
id = Column(BigInteger, primary_key=True, autoincrement=True)
post_id = Column(BigInteger, ForeignKey('posts.id'))
language_id = Column(BigInteger, ForeignKey('languages.id'))
title = Column(Unicode(255), nullable=False)
post = relationship('Post', uselist=False)
language = relationship('Language', uselist=False)
class PostTag(Base):
__tablename__ = 'post_tags'
id = Column(BigInteger, primary_key=True, autoincrement=True)
post_id = Column(BigInteger, ForeignKey('posts.id'))
tag_id = Column(BigInteger, ForeignKey('tags.id'))
language_id = Column(BigInteger, ForeignKey('languages.id'))
post = relationship('Post', uselist=False)
language = relationship('Language', uselist=False)
tag = relationship('Tag', uselist=False)
Я разделяю таблицу на posts
и post_translation
для многоязычной базы данных.
Также разделяю таблицу на tags
и post_tags
.
И ссылку tag_id (FK) - tags
таблица.
В этом случае мне нужно извлечь все сообщения, содержащие указанное c имя тега.
query = session.query(PostTag).options(
joinedload(PostTag.post).joinedload(Post.names)
).join(Tag).filter(Tag.name == 'python').options(
contains_eager(PostTag.tag)
).all()
for q in query:
print(q.post.tags)
Над кодом отлично работает. Но когда я регистрировал запрос,
2020-01-30 20:25:45,854 INFO sqlalchemy.engine.base.Engine SELECT tags.id AS tags_id, tags.name AS tags_name, post_tags.id AS post_tags_id, post_tags.post_id AS post_tags_post_id, post_tags.tag_id AS post_tags_tag_id, post_tags.language_id AS post_tags_language_id, post_translation_1.id AS post_translation_1_id, post_translation_1.post_id AS post_translation_1_post_id, post_translation_1.language_id AS post_translation_1_language_id, post_translation_1.title AS post_translation_1_title, posts_1.id AS posts_1_id
FROM post_tags INNER JOIN tags ON tags.id = post_tags.tag_id LEFT OUTER JOIN posts AS posts_1 ON posts_1.id = post_tags.post_id LEFT OUTER JOIN post_translation AS post_translation_1 ON posts_1.id = post_translation_1.post_id
WHERE tags.name = %(name_1)s
2020-01-30 20:25:45,854 INFO sqlalchemy.engine.base.Engine {'name_1': 'python'}
2020-01-30 20:25:45,856 INFO sqlalchemy.engine.base.Engine SELECT post_tags.id AS post_tags_id, post_tags.post_id AS post_tags_post_id, post_tags.tag_id AS post_tags_tag_id, post_tags.language_id AS post_tags_language_id
FROM post_tags
WHERE %(param_1)s = post_tags.post_id
2020-01-30 20:25:45,856 INFO sqlalchemy.engine.base.Engine {'param_1': 1}
[<model.PostTag object at 0x10951a710>, <model.PostTag object at 0x109522b90>]
2020-01-30 20:25:45,857 INFO sqlalchemy.engine.base.Engine SELECT post_tags.id AS post_tags_id, post_tags.post_id AS post_tags_post_id, post_tags.tag_id AS post_tags_tag_id, post_tags.language_id AS post_tags_language_id
FROM post_tags
WHERE %(param_1)s = post_tags.post_id
2020-01-30 20:25:45,857 INFO sqlalchemy.engine.base.Engine {'param_1': 3}
Как вы знаете, это вызвало проблемы N + 1 при доступе к тегам. (q.post.tags
)
Я не знаю, почему запрос произошел еще раз, несмотря на то, что уже объединены (и загружаются) таблица тегов.
Есть ли здесь какое-нибудь решение?
Спасибо.