Что это вообще
FHIR (Fast Healthcare Interoperability Resources) — стандарт HL7 для хранения и обмена медицинскими данными так, чтобы разные системы (больница, лаборатория, страховая, мобильное приложение) могли друг друга понимать.
Представь: пациент сходил к врачу, потом сдал кровь в лаборатории, потом ему выписали лекарство. Это три разных события в трёх разных системах. Каждая система пишет данные по-своему — у больницы свои поля в БД, у лаборатории свои, у аптеки свои. Когда нужно собрать полную картину про пациента — кто-то должен переводить между форматами.
FHIR говорит: «давайте все будем хранить медицинские данные в одном формате — наборе карточек, связанных между собой ссылками». Каждая карточка — JSON-документ описывающий одну вещь.
Спецификация: https://www.hl7.org/fhir/
Сегодня в продакшене у нас FHIR R4 — детальнее в fhir-versions (R4 / R5 / R6, design-trends, наши планы миграции).
Карточки и связи между ними
Каждая карточка — отдельный объект с уникальным ID. Карточки бывают разных типов (resource types):
Patient— карточка пациента (имя, дата рождения, контакты)Observation— карточка результата измерения (глюкоза = 5.5 ммоль/л)Condition— карточка диагноза (диабет 2 типа)MedicationRequest— карточка назначения (метформин 500мг 2р/день)Practitioner— карточка врачаOrganization— карточка организации (лаборатория, клиника)
И ещё ~140 других типов под разные сценарии — какие именно бывают типы, как они сгруппированы по модулям спецификации (Foundation / Clinical / Financial / Specialized), смотри fhir-resource-categories-overview.
Конкретный пример
Иван сдал кровь, по результатам поставили диагноз, назначили лечение. В FHIR это будет 5 карточек, связанных ссылками:
Patient
┌─────────────┐
│ id: pat-001 │
│ name: Иван │
│ born: 1980 │
└──────┬──────┘
│ subject
┌────────────────────┼────────────────────┐
▼ ▼ ▼
Observation Condition MedicationRequest
┌──────────────┐ ┌────────────┐ ┌──────────────┐
│ id: obs-001 │ │ id: cnd-1 │ │ id: med-1 │
│ code: глюк. │ │ code: T2DM │ │ med: метф. │
│ value: 5.5 │ │ recorder:→ │ │ requester:→ │
│ performer: → │ │ prac-1 │ │ prac-1 │
│ org-1 │ └────────────┘ └──────────────┘
└──────┬───────┘
│ performer
▼
Organization Practitioner
┌──────────────┐ ┌──────────────┐
│ id: org-1 │ │ id: prac-1 │
│ name: ЛабX │ │ name: Иванов │
└──────────────┘ └──────────────┘
Стрелки — это ссылки (тип Reference) между карточками. У Observation.subject — указание на пациента. У Condition.recorder — кто записал диагноз. У MedicationRequest.requester — кто назначил.
Каждая карточка может быть отдельно прочитана через REST API:
GET /Patient/pat-001 → JSON карточки пациента
GET /Observation/obs-001 → JSON карточки лабораторного результата
GET /Patient/pat-001/$everything → Bundle со всеми карточками пациента
Сравнение с реляционной БД
| SQL | FHIR |
|---|---|
таблица patient | resourceType Patient |
| строка в таблице | одна JSON-карточка |
id колонка | поле id карточки |
foreign key patient_id | Reference на Patient/pat-001 |
JOIN patients ON observations.patient_id | пройти по Observation.subject к Patient |
| схема таблицы | resource definition (StructureDefinition) |
Ключевые отличия:
- Схема публичная и стандартная. В SQL каждая больница придумывает свою; в FHIR — единая, опубликована HL7.
- Хранение как JSON-документы. Не таблицы с колонками, а отдельные документы. Любой FHIR-сервер раздаёт их через стандартный REST API.
- Ссылки через URL. Связи между ресурсами — не числовые
id, а строки видаPatient/pat-001. Можно ссылаться на пациента в чужой системе через absolute URL. - Schema-driven validation. FHIR-сервер сам проверяет валидность ресурса при write (cardinality, required fields, value sets); SQL обычно делает только тип-чек и базовые constraints.
Что делает FHIR полезным
- Один формат для всех. Если ты пишешь
Patient— он одинаково выглядит у больницы в США, лаборатории в РФ, мобильного приложения на Android. Можно exchange’иться без переводчиков. - REST API стандартный.
GET /Patient/123работает одинаково в любой FHIR-системе. Не надо изучать каждый custom API. - Эволюция через расширения. Если стандартного поля не хватает — есть механизм
extensionдля custom-добавлений. Downstream-consumer’ы могут их игнорировать без поломки (см. fhir-profiling).
Что читать дальше
Зная что есть карточки и связи между ними — можно углубляться по нужде:
- Содержимое одной карточки (cardinality, primitive types, DataTypes, references, meta, extensions, choice types, bundles) — fhir-resource-elements
- Конкретные виды карточек в нашем pipeline:
- fhir-observation — лаб-результаты и vital signs
- fhir-condition — диагнозы
- fhir-composition — наш центральный AI-документ
- fhir-bundle — упаковка нескольких карточек вместе (для exchange)
- fhir-careplan — follow-up рекомендации
- Версии стандарта R4 / R5 / R6 — fhir-versions
- Профилирование (как мы конкретизируем стандарт под себя) — fhir-profiling
- Meta-ресурсы (StructureDefinition / ValueSet / etc — те ресурсы, которые описывают сам стандарт) — fhir-conformance-resources
- FSH — DSL для авторства profiles — fsh
- Tooling (codegen, validators, clients) — fhir-tooling · fhir-code-generation
- Realm-IGs (что добавляется поверх base FHIR в США / РФ) — us-core · rucore
- Provenance + meta.tag — fhir-meta-tagging · fhir-resource-origin-and-lifecycle (как мы трекаем origin: chat / survey / document-import)
- LOINC — loinc (главная codesystem для лабораторных)