Some checks failed
Deploy on push / deploy (push) Failing after 8s
### 👥 Author Statistics Enhancement - **📊 Полная статистика авторов**: Добавлены все недостающие счётчики в AuthorStat - `topics`: Количество уникальных тем, в которых участвовал автор - `coauthors`: Количество соавторов - `replies_count`: Количество вызванных комментариев - `rating_shouts`: Рейтинг публикаций автора (сумма реакций LIKE/AGREE/ACCEPT/PROOF/CREDIT минус DISLIKE/DISAGREE/REJECT/DISPROOF) - `rating_comments`: Рейтинг комментариев автора (реакции на его комментарии) - `replies_count`: Количество вызванных комментариев - `comments`: Количество созданных комментариев и цитат - `viewed_shouts`: Общее количество просмотров всех публикаций автора - **🔄 Улучшенная сортировка**: Поддержка сортировки по всем новым полям статистики - **⚡ Оптимизированные запросы**: Batch-запросы для получения всей статистики одним вызовом - **🧪 Подробное логирование**: Эмодзи-маркеры для каждого типа статистики ### 🔧 Technical Implementation - **Resolvers**: Обновлён `load_authors_by` для включения всех счётчиков - **Database**: Оптимизированные SQL-запросы с JOIN для статистики - **Caching**: Интеграция с ViewedStorage для подсчёта просмотров - **GraphQL Schema**: Обновлён тип AuthorStat с новыми полями
11 KiB
11 KiB
📊 Система статистики авторов
Полная документация по расчёту и использованию статистики авторов в Discours.
🎯 Обзор
Система статистики авторов предоставляет многомерную оценку активности, популярности и вовлечённости каждого автора на платформе. Все метрики рассчитываются в реальном времени и кешируются для производительности.
📈 Метрики AuthorStat
# Статистика автора - полная метрика активности и популярности
type AuthorStat {
# Контент автора
shouts: Int # Количество опубликованных статей
topics: Int # Количество уникальных тем, в которых участвовал
comments: Int # Количество созданных комментариев и цитат
# Взаимодействие с другими авторами
coauthors: Int # Количество уникальных соавторов
followers: Int # Количество подписчиков
# Рейтинговая система
rating: Int # Общий рейтинг (rating_shouts + rating_comments)
rating_shouts: Int # Рейтинг публикаций (сумма реакций LIKE/AGREE/ACCEPT/PROOF/CREDIT минус DISLIKE/DISAGREE/REJECT/DISPROOF)
rating_comments: Int # Рейтинг комментариев (реакции на комментарии автора)
# Метрики вовлечённости
replies_count: Int # Количество ответов на контент автора (ответы на комментарии + комментарии на посты)
viewed_shouts: Int # Общее количество просмотров всех публикаций автора
}
📝 Контент автора
shouts: Int
Количество опубликованных статей
- Учитывает только статьи со статусом
published_at IS NOT NULL - Исключает удалённые статьи (
deleted_at IS NULL) - Подсчитывается через таблицу
shout_author
SELECT sa.author, COUNT(DISTINCT s.id) as shouts_count
FROM shout_author sa
JOIN shout s ON sa.shout = s.id
WHERE s.deleted_at IS NULL AND s.published_at IS NOT NULL
GROUP BY sa.author
topics: Int
Количество уникальных тем, в которых участвовал автор
- Подсчитывает уникальные темы через связку статей автора
- Основано на таблицах
shout_author→shout_topic
SELECT sa.author, COUNT(DISTINCT st.topic) as topics_count
FROM shout_author sa
JOIN shout s ON sa.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL
JOIN shout_topic st ON s.id = st.shout
GROUP BY sa.author
comments: Int
Количество созданных комментариев и цитат
- Включает реакции типа
COMMENTиQUOTE - Исключает удалённые комментарии
SELECT r.created_by, COUNT(DISTINCT r.id) as comments_count
FROM reaction r
JOIN shout s ON r.shout = s.id AND s.deleted_at IS NULL
WHERE r.deleted_at IS NULL AND r.kind IN ('COMMENT', 'QUOTE')
GROUP BY r.created_by
👥 Взаимодействие с другими авторами
coauthors: Int
Количество уникальных соавторов
- Подсчитывает авторов, с которыми автор публиковал совместные статьи
- Исключает самого автора из подсчёта
- Учитывает только опубликованные и неудалённые статьи
SELECT sa1.author, COUNT(DISTINCT sa2.author) as coauthors_count
FROM shout_author sa1
JOIN shout s ON sa1.shout = s.id
AND s.deleted_at IS NULL
AND s.published_at IS NOT NULL
JOIN shout_author sa2 ON s.id = sa2.shout
AND sa2.author != sa1.author -- исключаем самого автора
GROUP BY sa1.author
followers: Int
Количество подписчиков
- Прямой подсчёт из таблицы
author_follower
SELECT following, COUNT(DISTINCT follower) as followers_count
FROM author_follower
GROUP BY following
⭐ Рейтинговая система
rating: Int
Общий рейтинг автора
- Сумма
rating_shouts + rating_comments - Агрегированная метрика популярности контента
rating_shouts: Int
Рейтинг публикаций автора
- Сумма всех реакций на статьи автора
- Положительные реакции:
LIKE,AGREE,ACCEPT,PROOF,CREDIT(+1) - Отрицательные реакции:
DISLIKE,DISAGREE,REJECT,DISPROOF(-1) - Нейтральные реакции: остальные (0)
SELECT sa.author,
SUM(CASE
WHEN r.kind IN ('LIKE', 'AGREE', 'ACCEPT', 'PROOF', 'CREDIT') THEN 1
WHEN r.kind IN ('DISLIKE', 'DISAGREE', 'REJECT', 'DISPROOF') THEN -1
ELSE 0
END) as rating_shouts
FROM shout_author sa
JOIN shout s ON sa.shout = s.id AND s.deleted_at IS NULL AND s.published_at IS NOT NULL
JOIN reaction r ON s.id = r.shout AND r.deleted_at IS NULL
GROUP BY sa.author
rating_comments: Int
Рейтинг комментариев автора
- Аналогичная система для реакций на комментарии автора
- Подсчитывает реакции на комментарии через
reply_to
SELECT r1.created_by,
SUM(CASE
WHEN r2.kind IN ('LIKE', 'AGREE', 'ACCEPT', 'PROOF', 'CREDIT') THEN 1
WHEN r2.kind IN ('DISLIKE', 'DISAGREE', 'REJECT', 'DISPROOF') THEN -1
ELSE 0
END) as rating_comments
FROM reaction r1
JOIN reaction r2 ON r1.id = r2.reply_to AND r2.deleted_at IS NULL
WHERE r1.deleted_at IS NULL AND r1.kind IN ('COMMENT', 'QUOTE')
GROUP BY r1.created_by
🔄 Метрики вовлечённости
replies_count: Int
Количество ответов на контент автора
- Комплексная метрика, включающая:
- Ответы на комментарии автора (через
reply_to) - Комментарии на посты автора (прямые комментарии к статьям)
- Ответы на комментарии автора (через
Логика расчёта:
# Ответы на комментарии
replies_to_comments = COUNT(r2) WHERE r1.created_by = author AND r2.reply_to = r1.id
# Комментарии на посты
comments_on_posts = COUNT(r) WHERE sa.author = author AND r.shout = s.id
# Итого
replies_count = replies_to_comments + comments_on_posts
viewed_shouts: Int
Общее количество просмотров всех публикаций автора
- Интеграция с
ViewedStorage(Google Analytics) - Суммирует просмотры всех статей автора
- Обновляется асинхронно из внешних источников
🔍 API использования
GraphQL запрос
query LoadAuthors($by: AuthorsBy, $limit: Int, $offset: Int) {
load_authors_by(by: $by, limit: $limit, offset: $offset) {
id
slug
name
bio
pic
stat {
shouts
topics
coauthors
followers
rating
rating_shouts
rating_comments
comments
replies_count
viewed_shouts
}
}
}
Параметры сортировки
# Сортировка по количеству публикаций
{ "order": "shouts" }
# Сортировка по общему рейтингу
{ "order": "rating" }
# Сортировка по вовлечённости
{ "order": "replies_count" }
# Сортировка по просмотрам
{ "order": "viewed_shouts" }
⚡ Производительность
Кеширование
- Redis кеш для результатов запросов
- Ключи кеша:
authors:stats:limit={limit}:offset={offset}:order={order} - TTL: Настраивается в
cache.py
Оптимизации SQL
- Batch запросы для получения статистики всех авторов одновременно
- Подготовленные параметры для защиты от SQL-инъекций
- Индексы на ключевых полях (
author_id,shout_id,reaction.kind)
Сортировка
- SQL-уровень сортировки для метрик статистики
- Подзапросы с JOIN для производительности
- COALESCE для обработки NULL значений
🧪 Тестирование
Unit тесты
# Тестирование расчёта статистики
async def test_author_stats_calculation():
# Создаём тестовые данные
# Проверяем корректность расчёта каждой метрики
pass
# Тестирование сортировки
async def test_author_sorting():
# Проверяем сортировку по разным полям
pass
Интеграционные тесты
- Тестирование с реальными данными
- Проверка производительности на больших объёмах
- Валидация кеширования
🔧 Конфигурация
Переменные окружения
# Google Analytics для просмотров
GOOGLE_KEYFILE_PATH=/path/to/service-account.json
GOOGLE_PROPERTY_ID=your-property-id
# Redis для кеширования
REDIS_URL=redis://localhost:6379
Настройки реакций
Типы реакций определены в orm/reaction.py:
# Положительные (+1)
POSITIVE_REACTIONS = ["LIKE", "AGREE", "ACCEPT", "PROOF", "CREDIT"]
# Отрицательные (-1)
NEGATIVE_REACTIONS = ["DISLIKE", "DISAGREE", "REJECT", "DISPROOF"]
🚀 Развитие
Планируемые улучшения
- Исторические тренды статистики
- Сегментация по периодам времени
- Дополнительные метрики вовлечённости
- Персонализированные рекомендации на основе статистики
Известные ограничения
- Просмотры обновляются с задержкой (Google Analytics API)
- Большие объёмы данных могут замедлять запросы без кеша
- Сложные запросы сортировки требуют больше ресурсов