This commit is contained in:
parent
55a0474602
commit
d8496bf094
|
@ -1,6 +1,6 @@
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
from sqlalchemy.orm import aliased, joinedload, selectinload
|
from sqlalchemy.orm import aliased, joinedload
|
||||||
from sqlalchemy.sql import union
|
from sqlalchemy.sql import union
|
||||||
from sqlalchemy.sql.expression import (
|
from sqlalchemy.sql.expression import (
|
||||||
and_,
|
and_,
|
||||||
|
@ -32,9 +32,9 @@ def query_shouts(slug=None, shout_id=None):
|
||||||
Базовый запрос для получения публикаций с подзапросами статистики, авторов и тем,
|
Базовый запрос для получения публикаций с подзапросами статистики, авторов и тем,
|
||||||
с агрегированием в JSON.
|
с агрегированием в JSON.
|
||||||
"""
|
"""
|
||||||
comments_reaction = aliased(Reaction, name='comments_reaction')
|
comments_reaction = aliased(Reaction, name="comments_reaction")
|
||||||
ratings_reaction = aliased(Reaction, name='ratings_reaction')
|
ratings_reaction = aliased(Reaction, name="ratings_reaction")
|
||||||
last_reaction = aliased(Reaction, name='last_reaction')
|
last_reaction = aliased(Reaction, name="last_reaction")
|
||||||
|
|
||||||
# Подзапрос для уникальных авторов, агрегированных в JSON
|
# Подзапрос для уникальных авторов, агрегированных в JSON
|
||||||
authors_subquery = (
|
authors_subquery = (
|
||||||
|
@ -84,11 +84,11 @@ def query_shouts(slug=None, shout_id=None):
|
||||||
and_(
|
and_(
|
||||||
comments_reaction.shout == Shout.id,
|
comments_reaction.shout == Shout.id,
|
||||||
comments_reaction.kind == ReactionKind.COMMENT.value,
|
comments_reaction.kind == ReactionKind.COMMENT.value,
|
||||||
comments_reaction.deleted_at.is_(None)
|
comments_reaction.deleted_at.is_(None),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.scalar_subquery()
|
.scalar_subquery()
|
||||||
.label('comments_stat')
|
.label("comments_stat")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Подзапрос для рейтинга
|
# Подзапрос для рейтинга
|
||||||
|
@ -98,7 +98,7 @@ def query_shouts(slug=None, shout_id=None):
|
||||||
case(
|
case(
|
||||||
(ratings_reaction.kind == ReactionKind.LIKE.value, 1),
|
(ratings_reaction.kind == ReactionKind.LIKE.value, 1),
|
||||||
(ratings_reaction.kind == ReactionKind.DISLIKE.value, -1),
|
(ratings_reaction.kind == ReactionKind.DISLIKE.value, -1),
|
||||||
else_=0
|
else_=0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -107,11 +107,11 @@ def query_shouts(slug=None, shout_id=None):
|
||||||
and_(
|
and_(
|
||||||
ratings_reaction.shout == Shout.id,
|
ratings_reaction.shout == Shout.id,
|
||||||
ratings_reaction.reply_to.is_(None),
|
ratings_reaction.reply_to.is_(None),
|
||||||
ratings_reaction.deleted_at.is_(None)
|
ratings_reaction.deleted_at.is_(None),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.scalar_subquery()
|
.scalar_subquery()
|
||||||
.label('rating_stat')
|
.label("rating_stat")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Основной запрос с использованием подзапросов
|
# Основной запрос с использованием подзапросов
|
||||||
|
@ -132,9 +132,9 @@ def query_shouts(slug=None, shout_id=None):
|
||||||
.where(and_(Shout.published_at.is_not(None), Shout.deleted_at.is_(None)))
|
.where(and_(Shout.published_at.is_not(None), Shout.deleted_at.is_(None)))
|
||||||
.group_by(
|
.group_by(
|
||||||
Shout.id,
|
Shout.id,
|
||||||
text('authors_subquery.authors::text'),
|
text("authors_subquery.authors::text"),
|
||||||
text('topics_subquery.topics::text'),
|
text("topics_subquery.topics::text"),
|
||||||
text('topics_subquery.main_topic_slug')
|
text("topics_subquery.main_topic_slug"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -155,12 +155,71 @@ def get_shouts_with_stats(q, limit=50, offset=0, author_id=None):
|
||||||
:param offset: Смещение для пагинации.
|
:param offset: Смещение для пагинации.
|
||||||
:return: Список публикаций с включенной статистикой.
|
:return: Список публикаций с включенной статистикой.
|
||||||
"""
|
"""
|
||||||
# Основной запрос для получения публикаций и объединения их с подзапросами
|
# Определение алиасов подзапросов
|
||||||
q = (
|
authors_subquery = (
|
||||||
q.options(
|
select(
|
||||||
selectinload(Shout.authors), # Eagerly load authors
|
ShoutAuthor.shout.label("shout_id"),
|
||||||
selectinload(Shout.topics), # Eagerly load topics
|
func.json_agg(
|
||||||
|
func.json_build_object(
|
||||||
|
"id",
|
||||||
|
Author.id,
|
||||||
|
"name",
|
||||||
|
Author.name,
|
||||||
|
"slug",
|
||||||
|
Author.slug,
|
||||||
|
"pic",
|
||||||
|
Author.pic,
|
||||||
|
"caption",
|
||||||
|
ShoutAuthor.caption,
|
||||||
|
)
|
||||||
|
).label("authors"),
|
||||||
)
|
)
|
||||||
|
.join(Author, ShoutAuthor.author == Author.id)
|
||||||
|
.group_by(ShoutAuthor.shout)
|
||||||
|
.subquery("authors_subquery")
|
||||||
|
)
|
||||||
|
|
||||||
|
topics_subquery = (
|
||||||
|
select(
|
||||||
|
ShoutTopic.shout.label("shout_id"),
|
||||||
|
func.json_agg(
|
||||||
|
func.json_build_object(
|
||||||
|
"id", Topic.id, "title", Topic.title, "slug", Topic.slug, "is_main", ShoutTopic.main
|
||||||
|
)
|
||||||
|
).label("topics"),
|
||||||
|
func.max(func.case([(ShoutTopic.main, Topic.slug)])).label("main_topic_slug"),
|
||||||
|
)
|
||||||
|
.join(Topic, ShoutTopic.topic == Topic.id)
|
||||||
|
.group_by(ShoutTopic.shout)
|
||||||
|
.subquery("topics_subquery")
|
||||||
|
)
|
||||||
|
|
||||||
|
last_reaction = (
|
||||||
|
select(func.max(Reaction.created_at).label("last_reacted_at"))
|
||||||
|
.filter(Reaction.shout == Shout.id, Reaction.deleted_at.is_(None))
|
||||||
|
.subquery()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Основной запрос
|
||||||
|
q = (
|
||||||
|
select(
|
||||||
|
Shout,
|
||||||
|
func.count(func.distinct(Reaction.id)).label("comments_stat"),
|
||||||
|
func.sum(func.case([(Reaction.kind == "LIKE", 1), (Reaction.kind == "DISLIKE", -1)], else_=0)).label(
|
||||||
|
"rating_stat"
|
||||||
|
),
|
||||||
|
last_reaction.c.last_reacted_at,
|
||||||
|
authors_subquery.c.authors,
|
||||||
|
topics_subquery.c.topics,
|
||||||
|
topics_subquery.c.main_topic_slug,
|
||||||
|
)
|
||||||
|
.outerjoin(Reaction, Reaction.shout == Shout.id)
|
||||||
|
.outerjoin(authors_subquery, authors_subquery.c.shout_id == Shout.id)
|
||||||
|
.outerjoin(topics_subquery, topics_subquery.c.shout_id == Shout.id)
|
||||||
|
.outerjoin(last_reaction, last_reaction.c.shout_id == Shout.id)
|
||||||
|
.filter(Shout.published_at.isnot(None), Shout.deleted_at.is_(None), Shout.featured_at.isnot(None))
|
||||||
|
.group_by(Shout.id, authors_subquery.c.authors, topics_subquery.c.topics, topics_subquery.c.main_topic_slug)
|
||||||
|
.order_by(Shout.published_at.desc().nullslast())
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
)
|
)
|
||||||
|
@ -175,7 +234,6 @@ def get_shouts_with_stats(q, limit=50, offset=0, author_id=None):
|
||||||
for [
|
for [
|
||||||
shout,
|
shout,
|
||||||
comments_stat,
|
comments_stat,
|
||||||
# followers_stat,
|
|
||||||
rating_stat,
|
rating_stat,
|
||||||
last_reacted_at,
|
last_reacted_at,
|
||||||
authors_json,
|
authors_json,
|
||||||
|
@ -187,7 +245,6 @@ def get_shouts_with_stats(q, limit=50, offset=0, author_id=None):
|
||||||
shout.topics = [Topic(**topic) for topic in topics_json] if topics_json else []
|
shout.topics = [Topic(**topic) for topic in topics_json] if topics_json else []
|
||||||
shout.stat = {
|
shout.stat = {
|
||||||
"viewed": ViewedStorage.get_shout(shout.id),
|
"viewed": ViewedStorage.get_shout(shout.id),
|
||||||
# "followed": followers_stat or 0,
|
|
||||||
"rating": rating_stat or 0,
|
"rating": rating_stat or 0,
|
||||||
"commented": comments_stat or 0,
|
"commented": comments_stat or 0,
|
||||||
"last_reacted_at": last_reacted_at,
|
"last_reacted_at": last_reacted_at,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user