ETL Pipeline: JSON to PostgreSQL
Наш фундамент (схема базы данных в PostgreSQL) успешно заложен. Теперь мы переходим ко второму этапу — написанию скрипта (ETL Pipeline), который прочитает 140 000 JSON файлов с партиями и загрузит их в нашу базу.
User Review Required
IMPORTANT
Мне нужно знать точный путь к директории (или ZIP-архиву) на твоем Mac, где сейчас физически лежат эти 140 000 JSON файлов. Во время поиска я нашел только несколько тестовых файлов в
dicechess-lab.
Open Questions
- Формат JSON: Я посмотрел на
benchmark_games.jsonв репозиторииdicechess-lab. Я вижу, что там ходы лежат вgameMoveHistoryStateMapи для каждого микро-хода записан полный FEN и брошенные кубики. Является ли этот формат абсолютно идентичным для всех 140 000 партий, которые ты скачал с сайта? - Пакетная вставка (Batching): Для скорости импорта мы будем использовать пакетную вставку (batch inserts) по 1000 партий за раз. Это займет некоторое время. У нас будет прогресс-бар в консоли. Согласен ли ты на использование библиотеки
tqdmдля красивого вывода прогресса?
Proposed Changes
Мы создадим Python скрипт src/importer.py (или src/etl/import_games.py), который будет делать следующее:
1. Парсинг FEN (DFEN)
Из каждого состояния мы берем поле fen.
Мы разделяем его по пробелам.
parts = fen.split(" ")
normalized_fen = " ".join(parts[0:4]) # piece_placement, color, castling, en_passantЗатем мы считаем хэш: xxhash.xxh64(normalized_fen).intdigest().
2. Сборка микро-ходов в Turn
Поскольку в JSON записан каждый микро-ход (состояние до хода, состояние после первого микро-хода, после второго), скрипт должен объединять их в единый логический ход (Turn).
- Начало хода: Цвет игрока не меняется, кубики брошены (
dicesне пустой). Начальная позиция (position_id) фиксируется. - Микро-ходы: Мы собираем
gameMoveHistoryMove(например,e2e4,g1f3) в списокplayed_moves = ["e2e4", "g1f3"]. - Конец хода: Цвет активного игрока меняется (или партия завершается).
3. Кэширование позиций в памяти
Поскольку позиций могут быть миллионы, но многие из них повторяются, скрипт будет держать в памяти локальный словарь (dict) хешей позиций, чтобы не делать SELECT к базе данных для каждой позиции. Неизвестные позиции будут записываться в базу ON CONFLICT DO NOTHING (PostgreSQL INSERT ... ON CONFLICT).
4. Вставка данных
Порядок вставки для каждого пакета (например, 1000 JSON файлов):
- Распарсить все уникальные
Player→ ВставитьON CONFLICT DO NOTHING. - Распарсить все уникальные
Position→ ВставитьON CONFLICT DO NOTHING. - Вставить
Game. - Вставить
Turn. - Вставить
GameEvent.
Verification Plan
Automated Tests
- Мы напишем юнит-тест
tests/test_importer.pyдля логики группировки микро-ходов в Turn. - Запустим импортер на небольшой тестовой директории (например, из 10 партий) и проверим, что данные корректно легли в PostgreSQL.
Manual Verification
- После загрузки первых 1000 партий, мы выполним несколько SQL-запросов напрямую в базе данных (через DBeaver/psql), чтобы убедиться, что массивы ходов и JSONB-метаданные выглядят идеально.