Files
core/docs/author-statistics.md
Untone d65f8f9fa7
Some checks failed
Deploy on push / deploy (push) Failing after 8s
[0.9.17] - 2025-08-31
### 👥 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 с новыми полями
2025-08-31 20:01:40 +03:00

292 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 📊 Система статистики авторов
Полная документация по расчёту и использованию статистики авторов в 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)
- Большие объёмы данных могут замедлять запросы без кеша
- Сложные запросы сортировки требуют больше ресурсов