# Foreign Key Validation Guide

## Проверка ссылочной целостности данных

**Дата:** 30 декабря 2025  
**Версия:** 1.0

---

## 📋 Что такое Foreign Key Validation?

**Foreign Key (Внешний ключ)** - это поле в одной коллекции, которое ссылается на запись в другой коллекции.

**Пример:**
```
odf_results.athlete_code → odf_participants.code
```

Это означает: поле `athlete_code` в коллекции `odf_results` должно содержать значение, которое существует в поле `code` коллекции `odf_participants`.

### **Проблема:**

MongoDB **НЕ ПРОВЕРЯЕТ** автоматически существуют ли ссылки. Вы можете вставить:
```json
{
  "athlete_code": "9999999",
  "result": "72"
}
```

Даже если спортсмена с кодом `9999999` не существует в базе данных!

### **Решение:**

Наша система теперь **автоматически проверяет** все foreign key ссылки перед импортом и показывает какие записи имеют некорректные ссылки.

---

## ✅ Что реализовано

### **1. Настройка Foreign Keys через UI**

В **Settings → Collection Configuration** можно настроить:
- Какие поля являются foreign keys
- На какую коллекцию они ссылаются
- На какое поле в целевой коллекции они ссылаются

### **2. Автоматическая валидация**

При сравнении JSON vs DB система:
- Загружает все значения из целевых коллекций
- Проверяет существуют ли ссылки
- Показывает какие записи имеют некорректные ссылки

### **3. Детальные отчёты**

Система показывает:
- Сколько записей проверено
- Сколько прошли валидацию
- Сколько имеют ошибки
- Какие именно поля и значения некорректны

---

## 🔧 Как настроить Foreign Keys

### **Шаг 1: Открыть Settings**

1. Запустить приложение
2. Перейти в **⚙️ Settings**
3. Прокрутить до **📋 Collection Configuration**

### **Шаг 2: Выбрать коллекцию**

Выбрать коллекцию, для которой нужно настроить foreign keys.

**Пример:** `odf_results`

### **Шаг 3: Настроить Foreign Keys**

Прокрутить до секции **Foreign Key Relationships**.

**Пример настройки для `odf_results`:**

```
Number of Foreign Keys: 2

Foreign Key #1:
- Field in odf_results: athlete_code
- References Collection: odf_participants
- References Field: code

Foreign Key #2:
- Field in odf_results: competition_code
- References Collection: competitions
- References Field: code
```

### **Шаг 4: Сохранить**

Нажать **💾 Save Foreign Keys**.

✅ Готово! Теперь при импорте данных в `odf_results` система будет проверять:
- Существует ли `athlete_code` в `odf_participants.code`
- Существует ли `competition_code` в `competitions.code`

---

## 📊 Примеры конфигурации

### **Пример 1: odf_results**

**Связи:**
- `athlete_code` → `odf_participants.code`
- `competition_code` → `competitions.code`

**Конфигурация:**
```yaml
odf_results:
  foreign_keys:
    - field: athlete_code
      references_collection: odf_participants
      references_field: code
    - field: competition_code
      references_collection: competitions
      references_field: code
```

---

### **Пример 2: odf_participants**

**Связи:**
- `nationality` → `countries.code`
- `organisation_code` → `organisations.code`

**Конфигурация:**
```yaml
odf_participants:
  foreign_keys:
    - field: nationality
      references_collection: countries
      references_field: code
    - field: organisation_code
      references_collection: organisations
      references_field: code
```

---

### **Пример 3: participants**

**Связи:**
- `person_code` → `people.code`
- `competition_code` → `competitions.code`
- `organisation_code` → `organisations.code`

**Конфигурация:**
```yaml
participants:
  foreign_keys:
    - field: person_code
      references_collection: people
      references_field: code
    - field: competition_code
      references_collection: competitions
      references_field: code
    - field: organisation_code
      references_collection: organisations
      references_field: code
```

---

## 🎯 Как работает валидация

### **Процесс:**

```
1. Загрузка JSON файлов
   ↓
2. Загрузка данных из MongoDB
   ↓
3. Сравнение (Exact/Duplicate/New)
   ↓
4. ПРОВЕРКА FOREIGN KEYS ← НОВОЕ!
   ↓
5. Отображение результатов
```

### **Что проверяется:**

Для каждой записи в JSON:
1. Извлекается значение поля foreign key
2. Проверяется существует ли это значение в целевой коллекции
3. Если НЕ существует → запись помечается как **INVALID**

### **Пример:**

**JSON запись:**
```json
{
  "athlete_code": "1234567",
  "competition_code": "GOLF2024",
  "result": "72"
}
```

**Проверка:**
1. Ищем `1234567` в `odf_participants.code` → ✅ Найдено
2. Ищем `GOLF2024` в `competitions.code` → ❌ НЕ найдено

**Результат:** Запись **INVALID** - `competition_code` не существует.

---

## 📺 Как выглядит в UI

### **Если все ссылки корректны:**

```
✅ Foreign Key Validation Passed

- Records Checked: 150
- Foreign Keys Checked: 2

All foreign key references are valid!
```

### **Если есть некорректные ссылки:**

```
❌ Foreign Key Validation Failed

- Total Records Checked: 150
- Valid Records: 145
- Invalid Records: 5
- Foreign Keys Checked: 2

⚠️ Some records have invalid foreign key references. See details below.
```

**Детали:**
```
❌ Invalid Foreign Key References

1. Record: 1234567
   ❌ Field competition_code = GOLF2024: 
      Referenced value 'GOLF2024' not found in competitions.code

2. Record: 7654321
   ❌ Field athlete_code = 9999999: 
      Referenced value '9999999' not found in odf_participants.code
```

---

## 🔍 Что делать с некорректными ссылками

### **Вариант 1: Исправить данные в JSON**

Если ссылка некорректна - исправить JSON файл перед импортом.

**Пример:**
```json
// Было:
{
  "competition_code": "GOLF2024"  // Не существует
}

// Стало:
{
  "competition_code": "GOLF_2024"  // Существует
}
```

### **Вариант 2: Добавить недостающие записи**

Если ссылка корректна, но запись ещё не импортирована - сначала импортировать целевую коллекцию.

**Пример:**
1. Сначала импортировать `competitions` (чтобы создать `GOLF2024`)
2. Потом импортировать `odf_results` (которые ссылаются на `GOLF2024`)

### **Вариант 3: Отключить валидацию**

Если валидация не нужна - удалить foreign keys в Settings.

**Когда отключать:**
- Данные импортируются в правильном порядке
- Ссылки будут добавлены позже
- Тестовая среда

---

## ⚙️ Технические детали

### **Производительность:**

Система использует **кэширование** для эффективности:
1. Загружает все distinct значения из целевых коллекций один раз
2. Сохраняет в памяти
3. Проверяет все записи против кэша

**Пример:**
```python
# Загрузить все коды спортсменов один раз
athlete_codes = mongo.get_distinct_values('odf_participants', 'code')
# Результат: ['1234567', '2345678', '3456789', ...]

# Проверить каждую запись
for record in json_records:
    if record['athlete_code'] not in athlete_codes:
        # Некорректная ссылка!
```

### **Поддержка вложенных полей:**

Система поддерживает dot notation для вложенных полей:

```yaml
foreign_keys:
  - field: person.code
    references_collection: people
    references_field: code
```

### **Null/Empty значения:**

Пустые значения **НЕ проверяются**:
```json
{
  "athlete_code": null  // OK - не проверяется
}
```

Это позволяет иметь опциональные foreign keys.

---

## 📋 Рекомендации

### **1. Настроить foreign keys для всех коллекций**

Для каждой коллекции определить какие поля ссылаются на другие коллекции.

### **2. Импортировать в правильном порядке**

**Правильный порядок:**
1. Справочники (countries, organisations, people, competitions)
2. Основные данные (participants, odf_participants)
3. Результаты (odf_results, odf_rankings)

### **3. Проверять результаты валидации**

Всегда проверять есть ли некорректные ссылки перед импортом.

### **4. Исправлять ошибки до импорта**

Не импортировать записи с некорректными ссылками - это приведёт к проблемам целостности данных.

---

## 🎓 Практический пример

### **Сценарий:**

Импортируем результаты турнира по гольфу.

### **Шаг 1: Настроить foreign keys**

**Settings → odf_results:**
```
Foreign Key #1:
- Field: athlete_code
- References: odf_participants.code

Foreign Key #2:
- Field: competition_code
- References: competitions.code
```

### **Шаг 2: Загрузить JSON**

**JSON vs DB → Load & Compare**

### **Шаг 3: Проверить результаты**

```
❌ Foreign Key Validation Failed

Invalid Records: 3

1. Record: Result #1
   ❌ Field athlete_code = 9999999: 
      Referenced value '9999999' not found in odf_participants.code
```

### **Шаг 4: Исправить данные**

Проверить JSON файл - спортсмен с кодом `9999999` не существует.

**Варианты:**
- Исправить код на существующий
- Сначала импортировать спортсмена
- Удалить эту запись из JSON

### **Шаг 5: Повторить импорт**

После исправления - повторить Load & Compare.

```
✅ Foreign Key Validation Passed

All foreign key references are valid!
```

### **Шаг 6: Импортировать**

Теперь можно безопасно импортировать данные.

---

## 🔧 Устранение проблем

### **Проблема: "Target collection not found"**

**Причина:** Целевая коллекция пустая или не существует.

**Решение:**
1. Проверить что целевая коллекция существует в MongoDB
2. Импортировать данные в целевую коллекцию сначала
3. Проверить правильность названия коллекции в конфигурации

### **Проблема: "Referenced value not found"**

**Причина:** Значение не существует в целевой коллекции.

**Решение:**
1. Проверить правильность значения в JSON
2. Проверить существует ли запись в целевой коллекции
3. Импортировать недостающую запись
4. Исправить значение в JSON

### **Проблема: Валидация слишком медленная**

**Причина:** Большое количество записей или foreign keys.

**Решение:**
1. Система использует кэширование - должна быть быстрой
2. Если медленно - проверить размер целевых коллекций
3. Можно временно отключить валидацию для тестирования

---

## 📊 Сравнение: До и После

### **ДО (без валидации):**

```
Импорт → MongoDB

Результат:
- Записи импортированы
- Некорректные ссылки НЕ обнаружены
- Проблемы целостности данных
- Сложно найти ошибки
```

### **ПОСЛЕ (с валидацией):**

```
Импорт → Валидация → MongoDB

Результат:
- Некорректные ссылки обнаружены ДО импорта
- Пользователь видит ошибки
- Может исправить перед импортом
- Целостность данных гарантирована
```

---

## ✅ Преимущества

### **1. Целостность данных**
- Гарантия что все ссылки корректны
- Нет "битых" ссылок в базе данных

### **2. Раннее обнаружение ошибок**
- Ошибки находятся ДО импорта
- Не нужно чистить базу данных после

### **3. Понятные сообщения**
- Точно указано какое поле и значение некорректно
- Легко исправить

### **4. Гибкость**
- Можно настроить для любых коллекций
- Можно включить/выключить
- Поддержка вложенных полей

---

## 🎯 Итог

**Foreign Key Validation** - это мощный инструмент для обеспечения целостности данных.

**Используйте его для:**
- ✅ Проверки ссылок между коллекциями
- ✅ Обнаружения ошибок до импорта
- ✅ Гарантии качества данных
- ✅ Упрощения отладки

**Настройте один раз - проверяйте всегда!**

---

**Дата создания:** 30 декабря 2025  
**Версия:** 1.0  
**Связанные документы:** DATABASE_ARCHITECTURE.md, PRODUCTION_READINESS.md
