separate-subq
Some checks failed
Deploy on push / deploy (push) Failing after 10s

This commit is contained in:
Untone 2024-10-31 19:11:41 +03:00
parent 62370b94b3
commit f29eb5f35a

View File

@ -31,8 +31,8 @@ def query_shouts():
""" """
Базовый запрос для получения публикаций с подзапросами статистики, авторов и тем. Базовый запрос для получения публикаций с подзапросами статистики, авторов и тем.
""" """
# Подзапрос для реакций и статистики (объединяем только эту часть) # Подзапросы для статистики реакций
reactions_subquery = ( rating_subquery = (
select( select(
func.sum( func.sum(
case( case(
@ -40,19 +40,34 @@ def query_shouts():
(Reaction.kind == ReactionKind.DISLIKE.value, -1), (Reaction.kind == ReactionKind.DISLIKE.value, -1),
else_=0, else_=0,
) )
).label("rating_stat"), )
func.count(distinct(case((Reaction.kind == ReactionKind.COMMENT.value, Reaction.id), else_=None))).label(
"comments_stat"
),
func.max(Reaction.created_at).label("last_reacted_at"),
) )
.select_from(Reaction) .select_from(Reaction)
.where(and_(Reaction.shout == Shout.id, Reaction.reply_to.is_(None), Reaction.deleted_at.is_(None))) .where(and_(Reaction.shout == Shout.id, Reaction.reply_to.is_(None), Reaction.deleted_at.is_(None)))
.correlate(Shout) .correlate(Shout)
.scalar_subquery() .scalar_subquery()
.label("rating_stat")
) )
# Остальные подзапросы оставляем как есть comments_subquery = (
select(func.count(distinct(case((Reaction.kind == ReactionKind.COMMENT.value, Reaction.id), else_=None))))
.select_from(Reaction)
.where(and_(Reaction.shout == Shout.id, Reaction.reply_to.is_(None), Reaction.deleted_at.is_(None)))
.correlate(Shout)
.scalar_subquery()
.label("comments_stat")
)
last_reaction_subquery = (
select(func.max(Reaction.created_at))
.select_from(Reaction)
.where(and_(Reaction.shout == Shout.id, Reaction.reply_to.is_(None), Reaction.deleted_at.is_(None)))
.correlate(Shout)
.scalar_subquery()
.label("last_reacted_at")
)
# Остальные подзапросы остаются без изменений
authors_subquery = ( authors_subquery = (
select( select(
func.json_agg( func.json_agg(
@ -66,30 +81,6 @@ def query_shouts():
.scalar_subquery() .scalar_subquery()
) )
# Подзапрос для уникальных тем, агрегированных в JSON
topics_subquery = (
select(
func.json_agg(func.json_build_object("id", Topic.id, "title", Topic.title, "slug", Topic.slug)).label(
"topics"
)
)
.select_from(ShoutTopic)
.join(Topic, ShoutTopic.topic == Topic.id)
.where(ShoutTopic.shout == Shout.id)
.correlate(Shout)
.scalar_subquery()
)
# Новый подзапрос для main_topic_slug
main_topic_subquery = (
select(func.max(Topic.slug).label("main_topic_slug"))
.select_from(ShoutTopic)
.join(Topic, ShoutTopic.topic == Topic.id)
.where(and_(ShoutTopic.shout == Shout.id, ShoutTopic.main.is_(True)))
.correlate(Shout)
.scalar_subquery()
)
captions_subquery = ( captions_subquery = (
select( select(
func.json_agg(func.json_build_object("author_id", Author.id, "caption", ShoutAuthor.caption)).label( func.json_agg(func.json_build_object("author_id", Author.id, "caption", ShoutAuthor.caption)).label(
@ -103,11 +94,36 @@ def query_shouts():
.scalar_subquery() .scalar_subquery()
) )
topics_subquery = (
select(
func.json_agg(func.json_build_object("id", Topic.id, "title", Topic.title, "slug", Topic.slug)).label(
"topics"
)
)
.select_from(ShoutTopic)
.join(Topic, ShoutTopic.topic == Topic.id)
.where(ShoutTopic.shout == Shout.id)
.correlate(Shout)
.scalar_subquery()
)
main_topic_subquery = (
select(func.max(Topic.slug))
.select_from(ShoutTopic)
.join(Topic, ShoutTopic.topic == Topic.id)
.where(and_(ShoutTopic.shout == Shout.id, ShoutTopic.main.is_(True)))
.correlate(Shout)
.scalar_subquery()
.label("main_topic_slug")
)
# Основной запрос # Основной запрос
q = ( q = (
select( select(
Shout, Shout,
reactions_subquery, rating_subquery,
comments_subquery,
last_reaction_subquery,
authors_subquery, authors_subquery,
captions_subquery, captions_subquery,
topics_subquery, topics_subquery,
@ -124,7 +140,6 @@ def query_shouts():
def get_shouts_with_stats(q, limit=20, offset=0, author_id=None): def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
""" """
Получение публикаций со статистикой. Получение публикаций со статистикой.
:param q: Базовый запрос публикаций :param q: Базовый запрос публикаций
:param limit: Ограничение количества результатов :param limit: Ограничение количества результатов
:param offset: Смещение для пагинации :param offset: Смещение для пагинации
@ -145,18 +160,25 @@ def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
with local_session() as session: with local_session() as session:
results = session.execute(q).all() results = session.execute(q).all()
for [shout, reactions_stat, authors_json, captions_json, topics_json, main_topic_slug] in results: for [
# Базовые данные публикации shout,
rating_stat,
comments_stat,
last_reacted_at,
authors_json,
captions_json,
topics_json,
main_topic_slug,
] in results:
shout_dict = shout.dict() shout_dict = shout.dict()
# Добавление статистики просмотров # Добавление статистики просмотров
viewed_stat = ViewedStorage.get_shout(shout_slug=shout.slug) viewed_stat = ViewedStorage.get_shout(shout_slug=shout.slug, shout_id=shout.id)
# Обработка авторов и их подписей # Обработка авторов и их подписей
authors = authors_json or [] authors = authors_json or []
captions = captions_json or [] captions = captions_json or []
# Объединяем авторов с их подписями
for author in authors: for author in authors:
caption_item = next((c for c in captions if c["author_id"] == author["id"]), None) caption_item = next((c for c in captions if c["author_id"] == author["id"]), None)
if caption_item: if caption_item:
@ -175,9 +197,9 @@ def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
"main_topic": main_topic_slug, "main_topic": main_topic_slug,
"stat": { "stat": {
"viewed": viewed_stat or 0, "viewed": viewed_stat or 0,
"rating": reactions_stat.rating_stat or 0, "rating": rating_stat or 0,
"commented": reactions_stat.comments_stat or 0, "commented": comments_stat or 0,
"last_reacted_at": reactions_stat.last_reacted_at, "last_reacted_at": last_reacted_at,
}, },
} }
) )