SCDB

SCDB - База данных образовательных учреждений РФ

Open Source система для автоматического парсинга и обработки данных об образовательных учреждениях из открытых источников. Включает Server (REST API) и Updater (парсер данных).

Содержательная база

57,693

Образовательных учреждений

8

Федеральных округов

85

Регионов

1,117

Городов

Общеобразовательные

47,251

Среднее профессиональное образование

5,038

Дошкольное образование

1,940

Высшее образование

732

О проекте

SCDB (School Database) - это система управления базой данных образовательных организаций, состоящая из двух основных микросервисов: SCDB Server (REST API) и SCDB Updater (система обновления данных). Данные собираются из открытых источников и других официальных реестров.

Go 1.24.3

Основной язык разработки для SCDB Server и SCDB Updater. Выбран за высокую производительность при обработке XML данных

SCDB Updater

Система обновления данных с поддержкой типов учреждений и географического расположения. Парсит сырые данные о сертификатах, импортирует в базу данных

SCDB Server

REST API сервер на Go с Gin framework. Предоставляет эндпоинты для получения данных с фильтрацией по регионам, типам образования и пагинацией

PostgreSQL 17.4

Реляционная база данных с таблицами для организаций, регионов, городов, федеральных округов и типов образования. Полная структура связей

Docker & Docker Compose

Готовые Docker-образы для быстрого развертывания всей системы. Возможность поставки demo режима

Open Source

Полностью открытый исходный код под MIT лицензией. Два независимых репозитория: Server и Updater для гибкой архитектуры

🚀 Самый быстрый старт

Если вам хочется посмотреть итоговый результат и не хочется разворачивать базу данных и все это дело — я могу скинуть вам готовый демо режим в Docker образе с готовой пошаговой простой инструкцией!😊

Технологический стек

Go 1.24.3

Основной язык разработки для SCDB Server и SCDB Updater. Высокая производительность и простота развертывания

PostgreSQL 17.4

Реляционная база данных для хранения структурированных данных с индексами для быстрого поиска

Docker & Docker Compose

Контейнеризация для упрощения развертывания и обеспечения консистентности окружения

Gin
Gin Web Framework

Быстрый HTTP веб-фреймворк для Go, используемый в SCDB Server для создания REST API

Архитектура системы

Система состоит из двух независимых микросервисов: SCDB Updater для парсинга и обновления данных и SCDB Server для предоставления REST API.

1
SCDB Updater

Система обновления данных выполняет последовательную инициализацию: федеральные округа → регионы → города → типы организаций → образовательные учреждения. Использует транзакции PostgreSQL для атомарности операций и COPY для быстрой загрузки больших объемов данных.

package main

import (
	"gitlab.com/scdb/updater/internal/config"
	"gitlab.com/scdb/updater/internal/database"
	"gitlab.com/scdb/updater/internal/logger"
	"gitlab.com/scdb/updater/internal/services"
)

func main() {
	config.LoadConfig()
	database.Connect()

	// Последовательная инициализация данных
	districts := services.SeedFederalDistricts()
	services.SeedRegions(districts)
	services.SeedCities()
	services.SeedOrganisationsTypes()
	services.SeedOrganisations()

	defer database.DB.Close()
}
2
Оптимизированная загрузка организаций

Процесс загрузки образовательных учреждений оптимизирован для работы с большими объемами данных: отключение триггеров, использование временных таблиц, COPY операции, пакетная обработка по 1000 записей, исключение дубликатов через DISTINCT ON.

func SeedOrganisations() {
	start := time.Now()
	data := utils.GetDataParsedXML()

	// Транзакция для атомарности операций
	tx, err := database.DB.Begin()
	if err != nil {
		logger.Fatal("Ошибка при начале транзакции:", err)
	}

	// Отключаем триггеры для ускорения
	_, err = tx.Exec("ALTER TABLE education_organizations DISABLE TRIGGER ALL;")

	// Создаем временную таблицу для COPY
	_, err = tx.Exec(`
		CREATE TEMP TABLE temp_education_organizations (
			id text, full_name text, short_name text,
			head_edu_org_id text, is_branch boolean,
			post_address text, phone text, fax text,
			email text, web_site text, ogrn text,
			inn text, kpp text, head_post text,
			head_name text, form_name text,
			kind_name text, type_name text,
			fk_city_id text, fk_region_id int,
			fk_federal_district_id int,
			fk_education_type_key text
		) ON COMMIT DROP;
	`)

	// Используем COPY для быстрой загрузки
	stmt, err := tx.Prepare(pq.CopyIn("temp_education_organizations", ...))

	// Обрабатываем данные пакетами по 1000 записей
	for i, cert := range data.Certificates {
		org := cert.ActualEducationOrganization
		cityId, regionId, federalDistrictId, orgType := 
			utils.ProcessOrganization(org, citiesMap, regionsMap, ...)
		
		_, err = stmt.Exec(org.ID, org.FullName, ...)
	}

	// Вставляем из временной таблицы с исключением дубликатов
	_, err = tx.Exec(`
		INSERT INTO education_organizations
		SELECT DISTINCT ON (id) *
		FROM temp_education_organizations
		ON CONFLICT (id) DO NOTHING;
	`)

	tx.Commit()
}
3
SCDB Server - REST API

REST API сервер на Go с использованием Gin framework. Включает демо-лимиты для ограничения запросов, CORS настройки. Предоставляет эндпоинты для получения организаций с фильтрацией по федеральным округам, регионам, городам, типам образования, поиском и пагинацией.

// SCDB Server - настройка роутера
func SetupRouter() *gin.Engine {
	router := gin.Default()
	
	// Инициализируем демо-лимитер
	middleware.InitDemoLimiter()
	
	// CORS настройки
	router.Use(cors.New(cors.Config{
		AllowOrigins:     []string{config.AppConfig.WEBUrl},
		AllowMethods:     []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
		AllowHeaders:     []string{"Origin", "Content-Type", "Authorization"},
		ExposeHeaders:    []string{"Content-Length", "X-Demo-Image-ID", "X-Demo-Requests-Used", "X-Demo-Requests-Limit", "X-Demo-Requests-Remaining"},
		AllowCredentials: true,
		MaxAge:           12 * time.Hour,
	}))
	
	// Публичные маршруты
	public := router.Group("/api")
	{
		public.POST("/register", controllers.Register)
		public.POST("/login", controllers.Login)
		public.GET("/stats", controllers.GetStats)
		public.GET("/demo/stats", controllers.GetDemoStats)
	}
	
	// Защищенные маршруты с демо-лимитами
	protected := router.Group("/api")
	protected.Use(middleware.DemoLimitMiddleware())
	protected.Use(middleware.AuthMiddleware())
	{
		protected.GET("/organizations", controllers.GetOrganizations)
		protected.GET("/organizations/:id", controllers.GetOrganisationById)
	}
	
	return router
}

// Контроллер для получения организаций
func GetOrganizations(c *gin.Context) {
	search := c.Query("search")
	page, _ := strconv.Atoi(c.Query("page"))
	if page < 1 { page = 1 }
	
	perPage, _ := strconv.Atoi(c.Query("per_page"))
	if perPage < 1 { perPage = 20 }
	
	// Ограничения в демо-режиме
	if config.AppConfig.DemoMode && perPage > 50 {
		perPage = 50
	}
	
	// Параметры фильтрации
	var federalDistrictID *int
	if fdID, err := strconv.Atoi(c.Query("federal_district_id")); err == nil {
		federalDistrictID = &fdID
	}
	
	var regionID *int
	if rID, err := strconv.Atoi(c.Query("region_id")); err == nil {
		regionID = &rID
	}
	
	var cityID *string
	if cID := c.Query("city_id"); cID != "" {
		cityID = &cID
	}
	
	var educationTypeKey *string
	if etKey := c.Query("education_type_key"); etKey != "" {
		educationTypeKey = &etKey
	}
	
	organizations, total, err := repository.GetOrganizations(
		search, federalDistrictID, regionID, cityID, 
		educationTypeKey, perPage, (page-1)*perPage,
	)
	
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}
	
	c.JSON(http.StatusOK, gin.H{
		"data":        organizations,
		"total":       total,
		"page":        page,
		"per_page":    perPage,
		"total_pages": (total + perPage - 1) / perPage,
	})
}
4
Структура базы данных

PostgreSQL 17.4 с полной структурой связей между таблицами. Основная таблица education_organizations содержит все данные об учреждениях с внешними ключами на города, регионы, федеральные округа и типы образования. Оптимизированные индексы для быстрого поиска.

-- Структура базы данных
CREATE TABLE education_organizations (
	id text PRIMARY KEY,
	full_name text NOT NULL,
	short_name text,
	head_edu_org_id text,
	is_branch boolean DEFAULT false,
	post_address text,
	phone text,
	fax text,
	email text,
	web_site text,
	ogrn text,
	inn text,
	kpp text,
	head_post text,
	head_name text,
	form_name text,
	kind_name text,
	type_name text,
	fk_city_id text REFERENCES cities(id),
	fk_region_id int REFERENCES regions(id),
	fk_federal_district_id int REFERENCES federal_districts(id),
	fk_education_type_key text REFERENCES education_types(key)
);

-- Индексы для быстрого поиска
CREATE INDEX idx_orgs_region ON education_organizations(fk_region_id);
CREATE INDEX idx_orgs_city ON education_organizations(fk_city_id);
CREATE INDEX idx_orgs_type ON education_organizations(fk_education_type_key);
5
Docker Deployment

Готовый Docker Compose файл для быстрого развертывания системы. Включает PostgreSQL 17.4 с healthcheck, автоматической инициализацией базы данных через скрипты в docker-entrypoint-initdb.d, персистентным хранилищем и SCDB Server с зависимостью от готовности базы данных. Использует .env файл для конфигурации переменных окружения.

# Docker Compose для SCDB
version: "3.8"

services:
  db:
    image: postgres:17.4
    container_name: scdb-postgres
    restart: always
    env_file: .env
    ports:
      - "5432:5432"
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./internal/database/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user -d db"]
      interval: 5s
      timeout: 5s
      retries: 5

  app:
    build: .
    container_name: scdb-server
    restart: always
    env_file: .env
    ports:
      - "8080:8080"
    depends_on:
      db:
        condition: service_healthy

volumes:
  db_data:
6
Планы развития

В разработке: система API-ключей и авторизации, кеширование с Redis для повышения производительности, экспорт данных в CSV/Excel форматы, CLI интерфейс для импорта данных, система логирования и мониторинга производительности, веб-интерфейс для управления данными.

Примеры данных

Данным примером предствленные некоторые организации Центрального федерального округа

{
  "id": "0B0E1113-0B13-0C10-1311-0D130F0D120F100F0E0D",
  "full_name": "Автономная некоммерческая организация высшего образования «Институт кино и телевидения (ГИТР)»",
  "short_name": "АНО ВО ГИТР",
  "head_edu_org_id": "",
  "is_branch": false,
  "post_address": "123007, г. Москва, Хорошевское ш., д. 32 А",
  "phone": "+7(495) 787-65-11",
  "fax": "",
  "email": "aim@gitr.ru",
  "web_site": "www.gitr.ru",
  "ogrn": "1167700069228",
  "inn": "7714424400",
  "kpp": "771401001",
  "head_post": "47805583f3fe4c749a9a1e921e343336",
  "head_name": "Литовчин Юрий Михайлович",
  "form_name": "Автономные некоммерческие организации",
  "kind_name": "Начальная школа - детский сад",
  "type_name": "Образовательная организация высшего образования",
  "region_name": "",
  "federal_district_short_name": "",
  "federal_district_name": "Центральный федеральный округ",
  "created_at": "0001-01-01T00:00:00Z",
  "updated_at": "0001-01-01T00:00:00Z",
  "city_id": "0c5b2444-70a0-4932-980c-b4dc0d3f02b5",
  "region_id": 77,
  "federal_district_id": 1,
  "education_type_key": "general_education"
}

⚠️ Внимание: Портал открытых данных бывает недоступен. Сырой XML файл весит 1.2GB - мы не стали засорять GitHub этим файлом. Если у вас не получается скачать сырой XML, напишите в Telegram - с удовольствием отправим вам файл.

Часто задаваемые вопросы

Ответы на популярные вопросы о базе данных образовательных организаций

SCDB Server поставляется в виде Docker-образа. Для запуска выполните `docker-compose up -d` - это запустит PostgreSQL 17.4 и SCDB Server. Сервер будет доступен по адресу http://localhost:8080. Подробная инструкция в README на GitHub.

Для импорта данных используйте SCDB Updater - отдельный сервис для парсинга данных из реестра организаций Рособрнадзора. Updater поддерживает 10 типов образовательных учреждений и выполняет пошаговый импорт: федеральные округа → регионы → города → типы образования → организации.

SCDB поддерживает 10 типов: дошкольное, общее, среднее профессиональное, высшее, дополнительное, профессиональное обучение, специальное, военное, религиозное и международное образование. Каждый тип имеет ключевые слова для автоматической классификации.

SCDB Server предоставляет эндпоинты: GET /api/organizations/{id} - получение организации по ID, GET /api/organizations - список с фильтрацией и пагинацией, GET /api/stats - статистика. Поддерживается фильтрация по регионам, типам образования, поиск по названию.

Да, SCDB Server поддерживает демо-режим с ограниченным набором тестовых данных. Для создания демо-образа используйте docker-compose.demo.yml и скрипт обфускации данных.

Да, SCDB Updater работает независимо от SCDB Server. Вы можете использовать его для парсинга данных в свою базу данных или для других целей. Это отдельный сервис с собственным репозиторием и конфигурацией.

В разработке: система API-ключей и авторизации, кеширование с Redis, экспорт данных в CSV/Excel, импорт данных через CLI, система логирования и мониторинга производительности.

Проект открыт для контрибьюторов! Есть два репозитория: SCDB Server и SCDB Updater. Можно создавать issues с багами или feature requests, делать pull requests. Особенно приветствуются улучшения безопасности и производительности.

Проект распространяется под MIT лицензией, что позволяет свободно использовать, модифицировать и распространять код как в коммерческих, так и в некоммерческих целях.

Участвовать в проекте

SCDB состоит из двух репозиториев: SCDB Server (REST API) и SCDB Updater (парсер данных). Любой может внести свой вклад в развитие системы.

Поставить звезду

Поддержите проект, поставив звезду на GitHub репозитории. Это помогает проекту быть замеченным сообществом.

Star на GitHub
Сообщить о баге

Нашли ошибку в SCDB Server или SCDB Updater? Создайте issue с подробным описанием проблемы.

Создать Issue
Предложить идею

Есть идеи по улучшению API, безопасности или производительности? Предложите новые функции в issues.

Предложить
Написать код

Готовы внести код? Создайте fork, внесите изменения и отправьте pull request в любой из репозиториев.

Fork & PR
Репозитории проекта