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(
func.sum(
case(
@ -40,19 +40,34 @@ def query_shouts():
(Reaction.kind == ReactionKind.DISLIKE.value, -1),
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)
.where(and_(Reaction.shout == Shout.id, Reaction.reply_to.is_(None), Reaction.deleted_at.is_(None)))
.correlate(Shout)
.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 = (
select(
func.json_agg(
@ -66,30 +81,6 @@ def query_shouts():
.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 = (
select(
func.json_agg(func.json_build_object("author_id", Author.id, "caption", ShoutAuthor.caption)).label(
@ -103,11 +94,36 @@ def query_shouts():
.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 = (
select(
Shout,
reactions_subquery,
rating_subquery,
comments_subquery,
last_reaction_subquery,
authors_subquery,
captions_subquery,
topics_subquery,
@ -124,7 +140,6 @@ def query_shouts():
def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
"""
Получение публикаций со статистикой.
:param q: Базовый запрос публикаций
:param limit: Ограничение количества результатов
:param offset: Смещение для пагинации
@ -145,18 +160,25 @@ def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
with local_session() as session:
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()
# Добавление статистики просмотров
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 []
captions = captions_json or []
# Объединяем авторов с их подписями
for author in authors:
caption_item = next((c for c in captions if c["author_id"] == author["id"]), None)
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,
"stat": {
"viewed": viewed_stat or 0,
"rating": reactions_stat.rating_stat or 0,
"commented": reactions_stat.comments_stat or 0,
"last_reacted_at": reactions_stat.last_reacted_at,
"rating": rating_stat or 0,
"commented": comments_stat or 0,
"last_reacted_at": last_reacted_at,
},
}
)