This commit is contained in:
parent
8c05589168
commit
827300366d
|
@ -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")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user