This commit is contained in:
parent
62370b94b3
commit
f29eb5f35a
|
@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user