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 с новыми полями
292 lines
11 KiB
Markdown
292 lines
11 KiB
Markdown
# 📊 Система статистики авторов
|
||
|
||
Полная документация по расчёту и использованию статистики авторов в Discours.
|
||
|
||
## 🎯 Обзор
|
||
|
||
Система статистики авторов предоставляет многомерную оценку активности, популярности и вовлечённости каждого автора на платформе. Все метрики рассчитываются в реальном времени и кешируются для производительности.
|
||
|
||
## 📈 Метрики AuthorStat
|
||
|
||
```graphql
|
||
# Статистика автора - полная метрика активности и популярности
|
||
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`
|
||
|
||
```sql
|
||
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`
|
||
|
||
```sql
|
||
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`
|
||
- Исключает удалённые комментарии
|
||
|
||
```sql
|
||
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`
|
||
**Количество уникальных соавторов**
|
||
- Подсчитывает авторов, с которыми автор публиковал совместные статьи
|
||
- Исключает самого автора из подсчёта
|
||
- Учитывает только опубликованные и неудалённые статьи
|
||
|
||
```sql
|
||
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`
|
||
|
||
```sql
|
||
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)
|
||
|
||
```sql
|
||
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`
|
||
|
||
```sql
|
||
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`
|
||
**Количество ответов на контент автора**
|
||
- **Комплексная метрика**, включающая:
|
||
1. **Ответы на комментарии автора** (через `reply_to`)
|
||
2. **Комментарии на посты автора** (прямые комментарии к статьям)
|
||
|
||
Логика расчёта:
|
||
```python
|
||
# Ответы на комментарии
|
||
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 запрос
|
||
|
||
```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
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
### Параметры сортировки
|
||
|
||
```graphql
|
||
# Сортировка по количеству публикаций
|
||
{ "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 тесты
|
||
```python
|
||
# Тестирование расчёта статистики
|
||
async def test_author_stats_calculation():
|
||
# Создаём тестовые данные
|
||
# Проверяем корректность расчёта каждой метрики
|
||
pass
|
||
|
||
# Тестирование сортировки
|
||
async def test_author_sorting():
|
||
# Проверяем сортировку по разным полям
|
||
pass
|
||
```
|
||
|
||
### Интеграционные тесты
|
||
- Тестирование с реальными данными
|
||
- Проверка производительности на больших объёмах
|
||
- Валидация кеширования
|
||
|
||
## 🔧 Конфигурация
|
||
|
||
### Переменные окружения
|
||
```bash
|
||
# 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`:
|
||
```python
|
||
# Положительные (+1)
|
||
POSITIVE_REACTIONS = ["LIKE", "AGREE", "ACCEPT", "PROOF", "CREDIT"]
|
||
|
||
# Отрицательные (-1)
|
||
NEGATIVE_REACTIONS = ["DISLIKE", "DISAGREE", "REJECT", "DISPROOF"]
|
||
```
|
||
|
||
## 🚀 Развитие
|
||
|
||
### Планируемые улучшения
|
||
- [ ] Исторические тренды статистики
|
||
- [ ] Сегментация по периодам времени
|
||
- [ ] Дополнительные метрики вовлечённости
|
||
- [ ] Персонализированные рекомендации на основе статистики
|
||
|
||
### Известные ограничения
|
||
- Просмотры обновляются с задержкой (Google Analytics API)
|
||
- Большие объёмы данных могут замедлять запросы без кеша
|
||
- Сложные запросы сортировки требуют больше ресурсов
|