This commit is contained in:
parent
e2b6ae5e81
commit
e7b4e59b65
|
@ -68,7 +68,7 @@ def query_with_stat():
|
||||||
|
|
||||||
def get_shouts_with_links(info, q, limit=20, offset=0, author_id=None):
|
def get_shouts_with_links(info, 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)
|
||||||
|
@ -78,16 +78,20 @@ def get_shouts_with_links(info, q, limit=20, offset=0, author_id=None):
|
||||||
if offset:
|
if offset:
|
||||||
q = q.offset(offset)
|
q = q.offset(offset)
|
||||||
|
|
||||||
|
# Предварительно определяем флаги для запрашиваемых полей
|
||||||
|
includes_authors = has_field(info, "authors")
|
||||||
|
includes_topics = has_field(info, "topics")
|
||||||
|
includes_stat = has_field(info, "stat")
|
||||||
|
|
||||||
with local_session() as session:
|
with local_session() as session:
|
||||||
# 1. Получаем шауты одним запросом
|
shouts_result = session.execute(q).scalars().all()
|
||||||
shouts_result = session.execute(q).all()
|
|
||||||
if not shouts_result:
|
if not shouts_result:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
# 2. Получаем авторов и топики пакетным запросом
|
shout_ids = [shout.id for shout in shouts_result]
|
||||||
shout_ids = [row.Shout.id for row in shouts_result]
|
authors_and_topics = []
|
||||||
if has_field(info, "authors") or has_field(info, "topics"):
|
if includes_authors or includes_topics:
|
||||||
authors_and_topics = session.execute(
|
query = (
|
||||||
select(
|
select(
|
||||||
ShoutAuthor.shout.label("shout_id"),
|
ShoutAuthor.shout.label("shout_id"),
|
||||||
Author.id.label("author_id"),
|
Author.id.label("author_id"),
|
||||||
|
@ -104,38 +108,18 @@ def get_shouts_with_links(info, q, limit=20, offset=0, author_id=None):
|
||||||
.outerjoin(ShoutTopic, ShoutTopic.shout == ShoutAuthor.shout)
|
.outerjoin(ShoutTopic, ShoutTopic.shout == ShoutAuthor.shout)
|
||||||
.outerjoin(Topic, ShoutTopic.topic == Topic.id)
|
.outerjoin(Topic, ShoutTopic.topic == Topic.id)
|
||||||
.where(ShoutAuthor.shout.in_(shout_ids))
|
.where(ShoutAuthor.shout.in_(shout_ids))
|
||||||
).all()
|
)
|
||||||
|
authors_and_topics = session.execute(query).all()
|
||||||
|
|
||||||
# 3. Группируем данные эффективно
|
shouts_data = {
|
||||||
shouts_data = {}
|
shout.id: {**shout.dict(),
|
||||||
for row in shouts_result:
|
"authors": [],
|
||||||
shout = row.Shout
|
"topics": set()} for shout in shouts_result
|
||||||
shout_id = shout.id
|
|
||||||
shout_dict = shout.dict()
|
|
||||||
|
|
||||||
# Добавляем статистику только если она запрошена
|
|
||||||
if has_field(info, "stat"):
|
|
||||||
viewed_stat = ViewedStorage.get_shout(shout_id=shout_id) or 0
|
|
||||||
shout_dict["stat"] = {
|
|
||||||
"viewed": viewed_stat,
|
|
||||||
"commented": row.comments_count or 0,
|
|
||||||
"rating": row.rating or 0,
|
|
||||||
"last_reacted_at": row.last_reacted_at,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Инициализируем списки только для запрошенных полей
|
|
||||||
if has_field(info, "authors"):
|
|
||||||
shout_dict["authors"] = []
|
|
||||||
if has_field(info, "topics"):
|
|
||||||
shout_dict["topics"] = set() # используем set для уникальности
|
|
||||||
|
|
||||||
shouts_data[shout_id] = shout_dict
|
|
||||||
|
|
||||||
# 4. Заполняем связанные данные
|
|
||||||
for row in authors_and_topics:
|
for row in authors_and_topics:
|
||||||
shout_data = shouts_data[row.shout_id]
|
shout_data = shouts_data[row.shout_id]
|
||||||
|
if includes_authors:
|
||||||
# Добавляем автора
|
|
||||||
author = {
|
author = {
|
||||||
"id": row.author_id,
|
"id": row.author_id,
|
||||||
"name": row.author_name,
|
"name": row.author_name,
|
||||||
|
@ -146,8 +130,7 @@ def get_shouts_with_links(info, q, limit=20, offset=0, author_id=None):
|
||||||
if author not in shout_data["authors"]:
|
if author not in shout_data["authors"]:
|
||||||
shout_data["authors"].append(author)
|
shout_data["authors"].append(author)
|
||||||
|
|
||||||
# Добавляем топик если есть
|
if includes_topics and row.topic_id:
|
||||||
if row.topic_id:
|
|
||||||
topic = {
|
topic = {
|
||||||
"id": row.topic_id,
|
"id": row.topic_id,
|
||||||
"title": row.topic_title,
|
"title": row.topic_title,
|
||||||
|
@ -156,16 +139,23 @@ def get_shouts_with_links(info, q, limit=20, offset=0, author_id=None):
|
||||||
}
|
}
|
||||||
shout_data["topics"].add(tuple(topic.items()))
|
shout_data["topics"].add(tuple(topic.items()))
|
||||||
|
|
||||||
# 5. Финальная обработка и сортировка
|
for shout in shouts_data.values():
|
||||||
result = []
|
if includes_stat:
|
||||||
for shout_data in shouts_data.values():
|
shout_id = shout["id"]
|
||||||
# Конвертируем topics обратно в список словарей и сортируем
|
viewed_stat = ViewedStorage.get_shout(shout_id=shout_id) or 0
|
||||||
shout_data["topics"] = sorted(
|
shout["stat"] = {
|
||||||
[dict(t) for t in shout_data["topics"]], key=lambda x: (not x["is_main"], x["id"])
|
"viewed": viewed_stat,
|
||||||
)
|
"commented": shout.get("comments_count", 0),
|
||||||
result.append(shout_data)
|
"rating": shout.get("rating", 0),
|
||||||
|
"last_reacted_at": shout.get("last_reacted_at"),
|
||||||
|
}
|
||||||
|
|
||||||
return result
|
shout["topics"] = sorted(
|
||||||
|
[dict(t) for t in shout["topics"]],
|
||||||
|
key=lambda x: (not x["is_main"], x["id"])
|
||||||
|
)
|
||||||
|
|
||||||
|
return list(shouts_data.values())
|
||||||
|
|
||||||
|
|
||||||
def filter_my(info, session, q):
|
def filter_my(info, session, q):
|
||||||
|
@ -512,7 +502,7 @@ async def load_shouts_discussed(_, info, limit=50, offset=0):
|
||||||
:param info: Информация о контексте GraphQL.
|
:param info: Информация о контексте GraphQL.
|
||||||
:param limit: Максимальное количество публикаций.
|
:param limit: Максимальное количество публикаций.
|
||||||
:param offset: Смещне для пагинации.
|
:param offset: Смещне для пагинации.
|
||||||
:return: Список публикаций, обсужде<EFBFBD><EFBFBD>ных пользователем.
|
:return: Список публикаций, обсужденых пользователем.
|
||||||
"""
|
"""
|
||||||
author_id = info.context.get("author", {}).get("id")
|
author_id = info.context.get("author", {}).get("id")
|
||||||
if not author_id:
|
if not author_id:
|
||||||
|
@ -538,7 +528,7 @@ async def reacted_shouts_updates(info, follower_id: int, limit=50, offset=0) ->
|
||||||
Обновляет публикации, на которые подписан автор, с учетом реакци.
|
Обновляет публикации, на которые подписан автор, с учетом реакци.
|
||||||
|
|
||||||
:param follower_id: Идентификатор подписчика.
|
:param follower_id: Идентификатор подписчика.
|
||||||
:param limit: Коли<EFBFBD><EFBFBD>ество пу<EFBFBD><EFBFBD>ликаций для загрузки.
|
:param limit: Колиество пукликаций для загрузки.
|
||||||
:param offset: Смещение для пагинации.
|
:param offset: Смещение для пагинации.
|
||||||
:return: Список публикаций.
|
:return: Список публикаций.
|
||||||
"""
|
"""
|
||||||
|
|
Loading…
Reference in New Issue
Block a user