unrated-fix
Some checks failed
Deploy on push / deploy (push) Failing after 10s

This commit is contained in:
Untone 2024-10-31 19:57:09 +03:00
parent 8c05589168
commit 827300366d

View File

@ -72,8 +72,6 @@ def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
if author_id: if author_id:
q = q.filter(Shout.created_by == author_id) q = q.filter(Shout.created_by == author_id)
q = q.order_by(desc(Shout.published_at))
if limit: if limit:
q = q.limit(limit) q = q.limit(limit)
if offset: if offset:
@ -82,12 +80,11 @@ def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
with local_session() as session: with local_session() as session:
# 1. Получаем шауты одним запросом # 1. Получаем шауты одним запросом
shouts_result = session.execute(q).all() shouts_result = session.execute(q).all()
shout_ids = [row.Shout.id for row in shouts_result] if not shouts_result:
if not shout_ids:
return [] return []
# 2. Получаем авторов и топики пакетным запросом # 2. Получаем авторов и топики пакетным запросом
shout_ids = [row.Shout.id for row in shouts_result]
authors_and_topics = session.execute( authors_and_topics = session.execute(
select( select(
ShoutAuthor.shout.label('shout_id'), ShoutAuthor.shout.label('shout_id'),
@ -110,12 +107,13 @@ def get_shouts_with_stats(q, limit=20, offset=0, author_id=None):
# 3. Группируем данные эффективно # 3. Группируем данные эффективно
shouts_data = {} shouts_data = {}
for row in shouts_result: for row in shouts_result:
shout = row.Shout.__dict__ shout = row.shout
shout_id = shout['id'] shout_id = shout['id']
viewed_stat = ViewedStorage.get_shout(shout_id=shout_id) or 0
shouts_data[shout_id] = { shouts_data[shout_id] = {
**shout, **shout,
'stat': { 'stat': {
'viewed': ViewedStorage.get_shout(shout_id=shout_id) or 0, 'viewed': viewed_stat,
'commented': row.comments_count or 0, 'commented': row.comments_count or 0,
'rating': row.rating or 0, 'rating': row.rating or 0,
'last_reacted_at': row.last_reacted_at 'last_reacted_at': row.last_reacted_at
@ -295,7 +293,7 @@ async def load_shouts_by(_, _info, options):
query_order_by = desc(order_by) if options.get("order_by_desc", True) else asc(order_by) query_order_by = desc(order_by) if options.get("order_by_desc", True) else asc(order_by)
q = q.order_by(nulls_last(query_order_by)) q = q.order_by(nulls_last(query_order_by))
else: else:
q = q.order_by(Shout.published_at.desc().nulls_last()) q = q.order_by(Shout.published_at.desc())
# Ограничение и смещение # Ограничение и смещение
offset = options.get("offset", 0) offset = options.get("offset", 0)
@ -368,41 +366,36 @@ async def load_shouts_search(_, _info, text, limit=50, offset=0):
@query.field("load_shouts_unrated") @query.field("load_shouts_unrated")
async def load_shouts_unrated(_, info, limit: int = 50, offset: int = 0): async def load_shouts_unrated(_, info, limit=50, offset=0):
""" """
Загрузка публикаций с наименьшим количеством оценок. Загрузка публикаций с менее чем 3 реакциями типа LIKE/DISLIKE
""" """
rating_reaction = aliased(Reaction, name="rating_reaction") rated_shouts = (
select(Reaction.shout)
# Подзапрос для подсчета количества оценок (лайков и дизлайков)
ratings_count = (
select(func.count(distinct(rating_reaction.id)))
.select_from(rating_reaction)
.where( .where(
and_( and_(
rating_reaction.shout == Shout.id, Reaction.deleted_at.is_(None),
rating_reaction.reply_to.is_(None), Reaction.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value])
rating_reaction.deleted_at.is_(None),
rating_reaction.kind.in_([ReactionKind.LIKE.value, ReactionKind.DISLIKE.value]),
) )
) )
.correlate(Shout) .group_by(Reaction.shout)
.having(func.count('*') >= 3)
.scalar_subquery() .scalar_subquery()
.label("ratings_count")
) )
q = query_shouts() q = (
select(Shout)
.where(
and_(
Shout.published_at.is_not(None),
Shout.deleted_at.is_(None),
~Shout.id.in_(rated_shouts)
)
)
.order_by(desc(Shout.published_at))
)
# Добавляем подсчет рейтингов в основной запрос return get_shouts_with_stats(q, limit, offset)
q = q.add_columns(ratings_count)
# Фильтруем только опубликованные и не удаленные публикации
q = q.filter(and_(Shout.deleted_at.is_(None), Shout.published_at.is_not(None)))
# Сортируем по количеству оценок (по возрастанию) и случайно среди равных
q = q.order_by(ratings_count.asc(), func.random())
return get_shouts_with_stats(q, limit, offset=offset)
@query.field("load_shouts_random_top") @query.field("load_shouts_random_top")