diff --git a/resolvers/reader.py b/resolvers/reader.py index 6a324c84..84309029 100644 --- a/resolvers/reader.py +++ b/resolvers/reader.py @@ -1,7 +1,6 @@ from typing import List from sqlalchemy.orm import aliased, selectinload, joinedload from sqlalchemy.sql import union -from sqlalchemy.dialects.postgresql.types import sqltypes from sqlalchemy.sql.expression import ( and_, asc, @@ -37,6 +36,41 @@ def query_shouts(): shout_author = aliased(ShoutAuthor) shout_topic = aliased(ShoutTopic) + # Подзапросы для получения уникальных авторов и тем + authors_subquery = ( + select( + shout_author.shout.label("shout_id"), + func.json_agg( + func.json_build_object( + "id", Author.id, + "name", Author.name, + "slug", Author.slug, + "pic", Author.pic + ) + ).label("authors") + ) + .join(Author, Author.id == shout_author.author) + .group_by(shout_author.shout) + .alias("authors_subquery") + ) + + topics_subquery = ( + select( + shout_topic.shout.label("shout_id"), + func.json_agg( + func.json_build_object( + "id", Topic.id, + "title", Topic.title, + "body", Topic.body, + "slug", Topic.slug + ) + ).label("topics") + ) + .join(Topic, Topic.id == shout_topic.topic) + .group_by(shout_topic.shout) + .alias("topics_subquery") + ) + # Основной запрос с подзапросами для получения статистики, авторов и тем q = ( select( @@ -50,42 +84,14 @@ def query_shouts(): ) ).label("rating_stat"), func.max(aliased_reaction.created_at).label("last_reacted_at"), - func.array_agg( - func.distinct( - func.json_build_object( - "id", - Author.id, - "name", - Author.name, - "slug", - Author.slug, - "pic", - Author.pic, - ).cast(sqltypes.Text) # Преобразуем JSON в текст - ) - ).label("authors"), - func.array_agg( - func.distinct( - func.json_build_object( - "id", - Topic.id, - "title", - Topic.title, - "body", - Topic.body, - "slug", - Topic.slug, - ).cast(sqltypes.Text) # Преобразуем JSON в текст - ) - ).label("topics"), + authors_subquery.c.authors, + topics_subquery.c.topics, ) .outerjoin(aliased_reaction, aliased_reaction.shout == Shout.id) - .outerjoin(shout_author, shout_author.shout == Shout.id) - .outerjoin(Author, Author.id == shout_author.author) - .outerjoin(shout_topic, shout_topic.shout == Shout.id) - .outerjoin(Topic, Topic.id == shout_topic.topic) + .outerjoin(authors_subquery, authors_subquery.c.shout_id == Shout.id) + .outerjoin(topics_subquery, topics_subquery.c.shout_id == Shout.id) .where(and_(Shout.published_at.is_not(None), Shout.deleted_at.is_(None))) - .group_by(Shout.id) + .group_by(Shout.id, authors_subquery.c.authors, topics_subquery.c.topics) ) return q, aliased_reaction