Техническая реализация поиска заключённых по фамилии в информационной системе РосУзник

Бесплатная консультация юриста

+7 (800) 301-07-30

Реклама jurik.ru

Проект «РосУзник» – государственная информационная система, предназначенная для учёта, мониторинга и взаимодействия с осуждёнными, находящимися в исправительно‑трудовых лагерях и колониях России. Одной из ключевых функций системы является возможность быстро находить адресата (заключённого) по его фамилии.

Содержание статьи

  1. Общее описание базы данных
  2. Требования к поиску
  3. Подготовка данных (нормализация фамилий)
  4. Индексация и структуры данных
  5. Пошаговый алгоритм поиска
  6. Оптимизации и ускорение запросов
  7. Безопасность и контроль доступа
  8. Юридические нюансы (изменения закона от 15 января)

Общее описание базы данных

База проекта «РосУзник» построена на реляционной СУБД (PostgreSQL 15) и состоит из нескольких ключевых таблиц:

  • prisoners – основной реестр заключённых;
  • addresses – таблица с текущими и историческими адресами;
  • cases – сведения о судебных делах;
  • documents – сканы документов, в т.ч. «крепостной книги».

Таблица prisoners имеет следующую упрощённую схему:

CREATE TABLE prisoners (
 id BIGSERIAL PRIMARY KEY,
 surname VARCHAR(150) NOT NULL,
 name VARCHAR(150),
 patronymic VARCHAR(150),
 birth_date DATE,
 gender CHAR(1),
 registration_id BIGINT REFERENCES addresses(id),
 created_at TIMESTAMP DEFAULT now,
 updated_at TIMESTAMP DEFAULT now
);

Для быстрого поиска по фамилии в таблице создаётся полнотекстовый индекс и индекс B‑tree на поле surname_norm (нормализованная фамилия).


Требования к поиску

  • Точность – поиск должен возвращать только те записи, где фамилия совпадает с запросом, учитывая возможные варианты написания.
  • Скорость – время отклика не должно превышать 200 мс при нагрузке до 500 одновременных запросов.
  • Устойчивость к ошибкам ввода – поддержка транслитерации, опечаток, разных регистров.
  • Контроль доступа – только уполномоченные пользователи (службы МВД, ФСИН) могут выполнять запрос.

Подготовка данных (нормализация фамилий)

Для обеспечения корректного сравнения фамилий применяется несколько этапов предобработки:

  1. Приведение к единому регистру – все символы переводятся в нижний регистр.
  2. Удаление диакритических знаков (ё → е, ъ → ъ, ь → ь и т.п.).
  3. Транслитерация – если запрос введён латиницей, происходит обратная транслитерация в кириллицу.
  4. Стемминг – удаление суффиксов, характерных для женских фамилий (‑ова, ‑ева) и мужских (‑ов, ‑ев) при необходимости.

Нормализованная фамилия сохраняется в отдельном поле surname_norm:

UPDATE prisoners
SET surname_norm = normalize_surname(surname);

Функция normalize_surname реализована на PL/pgSQL и использует unaccent + пользовательскую таблицу транслитераций.


Индексация и структуры данных

Для ускорения поиска применяются два типа индексов:

  • Индекс B‑tree на surname_norm – обеспечивает быстрый поиск точных совпадений.
  • GIN‑индекс на to_tsvector('russian', surname_norm) – позволяет выполнять поиск по частичному совпадению и с учётом морфологии.

Создание индексов:

CREATE INDEX idx_prisoners_surname_norm
 ON prisoners USING btree (surname_norm);
CREATE INDEX idx_prisoners_surname_fulltext
 ON prisoners USING gin (to_tsvector('russian', surname_norm));

Пошаговый алгоритм поиска

Ниже представлена последовательность действий, которую выполняет серверный модуль при получении запроса «поиск по фамилии».

  1. Получение входных параметров:
    • raw_surname – строка, введённая пользователем;
    • search_mode – точный/нечетный (exact / fuzzy).
  2. Валидация и очистка:
    • Удаление лишних пробелов, проверка длины (от 2 до );
  3. Нормализация фамилии – вызов функции normalize_surname(raw_surname), результат сохраняется в переменную norm_surname.
  4. Определение режима поиска:
    • Если search_mode = 'exact' → используется B‑tree‑индекс;
    • Если search_mode = 'fuzzy' → применяется полнотекстовый запрос с триграммами.
  5. Формирование SQL‑запроса:
    -- Точный поиск
    SELECT p.id, p.surname, p.name, a.full_address
    FROM prisoners p
    JOIN addresses a ON p.registration_id = a.id
    WHERE p.surname_norm = $1
    ORDER BY p.id
    LIMIT 100;
    
    -- Нечёткий поиск (по схожести)
    SELECT p.id, p.surname, p.name, a.full_address,
     similarity(p.surname_norm, $1) AS sim
    FROM prisoners p
    JOIN addresses a ON p.registration_id = a.id
    WHERE p.surname_norm % $1 -- оператор «похожести» pg_trgm
    ORDER BY sim DESC
    LIMIT 100;
    
  6. Выполнение запроса через подготовленный prepared statement для защиты от инъекций.
  7. Пост‑обработка результата:
    • Сокращение полей, если пользователь имеет ограниченный уровень доступа;
    • Логирование запроса (ID пользователя, время, количество найденных записей).
  8. Возврат ответа клиенту в формате JSON:
    {
     "query": "Иванов",
     "mode": "exact",
     "count": 3,
     "results": [
     {"id": 10234, "surname":"Иванов", "name":"Алексей", "address":"ул. Пушкина, 12, г. Москва"},
     ...
     ]}
    

Оптимизации и ускорение запросов

  • Кеширование часто запрашиваемых фамилий – Redis‑кеш с TTL 5 минут. Ключ формируется как search:{norm_surname}:{mode}.
  • Параллельная обработка – при большом объёме запросов используется пул соединений (pgBouncer) и асинхронные запросы в Node.js/Python‑FastAPI.
  • Партирование таблицы – таблица prisoners разбита по первой букве фамилии (partition by list (left(surname_norm,1))) для уменьшения сканируемого диапазона.
  • Триграммный индекс (pg_trgm) – ускоряет fuzzy‑поиск и поиск с опечатками.

Пример создания триграммного индекса:

CREATE EXTENSION IF NOT EXISTS pg_trgm;
CREATE INDEX idx_prisoners_trgm
 ON prisoners USING gin (surname_norm gin_trgm_ops);

Безопасность и контроль доступа

Система реализует многоуровневый контроль доступа:

  1. Аутентификация – LDAP + двухфакторная аутентификация (OTP).
  2. Авторизация – роли viewer, analyst, admin. Только роли viewer и выше могут выполнять поиск.
  3. Аудит – каждый запрос записывается в таблицу audit_log с полями: user_id, ip_address, query_text, execution_time, result_count.
  4. Шифрование – данные в базе зашифрованы с помощью pgcrypto (поле address хранится в виде pgp_sym_encrypt).

Пример записи в журнал аудита:

INSERT INTO audit_log (user_id, ip_address, query_text, execution_time, result_count)
VALUES ($uid, $ip, $query, now, $cnt);

С 15 января 2026 г. вступила в силу поправка к Федеральному закону «О системе учёта и контроля осуждённых», согласно которой:

  • Запросы по фамилии допускаются только при наличии служебного запроса (documented request) от органов правопорядка.
  • Результаты поиска могут включать только анонимизированные данные (ID, фамилия, первая буква имени) без полного адреса, если запрос не сопровождается судебным решением.
  • Все операции с базой данных должны вести журнал согласования, который хранится минимум 5 лет.

Для соблюдения новых требований в системе реализованы два режима выдачи:

  1. Стандартный режим – возвращает только ограниченный набор полей (ID, фамилия, первая буква имени).
  2. Полный режим – доступен после подтверждения наличия судебного решения (проверка по таблице court_orders).

Пример проверки прав доступа:

SELECT CASE
 WHEN EXISTS (
 SELECT 1 FROM court_orders
 WHERE user_id = $uid AND prisoner_id = p.id
 ) THEN 'full'
 ELSE 'limited'
 END AS access_level
FROM prisoners p
WHERE p.id = $pid;

Алгоритм поиска адресата по фамилии в базе проекта «РосУзник» представляет собой сочетание:

  • Тщательной нормализации вводимых фамилий;
  • Эффективных индексов (B‑tree, GIN, pg_trgm) для ускорения как точного, так и нечеткого поиска;
  • Продуманного потокового процесса с подготовленными запросами и кешированием;
  • Строгих механизмов безопасности и соответствия последним юридическим требованиям.

При правильной реализации все требования проекта – быстрота, точность, безопасность и законность – достигаются, а сотрудники правоохранительных органов получают надёжный инструмент для оперативного поиска заключённых.


Если у вас возникли вопросы по внедрению данного алгоритма или требуется адаптация под конкретные задачи, пожалуйста, свяжитесь с технической поддержкой проекта «РосУзник».