Name: fhirbase-old
Owner: Fhirbase
Description: [WARNING] Fhirbase moved to https://github.com/fhirbase/fhirbase-plv8 postgresql persistance for FHIR
Created: 2013-11-12 10:36:56.0
Updated: 2016-02-17 10:02:09.0
Pushed: 2016-02-17 10:06:03.0
Size: 3321
Language: PLpgSQL
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
Open source relational storage for FHIR with document API
Powered by Health Samurai
Sponsored by:
Here is an interactive demo where you can get some practice in preparing and executing arbitrary queries on a demo database.
While crafting Health IT systems you begin to understand a value of properly chosen domain model. FHIR is an open source new generation lightweight standard for health data interoperability, which (we hope) could be used as an internal model for Health IT systems. FHIR is based on a concept of resource.
FHIRŽ is a next generation standards framework created by HL7. FHIR combines the best features of HL7 Version 2, Version 3 and CDAŽ product lines while leveraging the latest web standards and applying a tight focus on implementability.
In terms of Domain Driven Design, resource is an aggregate which consists of a root entity (having identity) and a set of aggregated value objects. In this readme we sometimes use DDD terminology so don't be confused.
There is a concern ? how to persist resources.
The simplest solution is just to save them as text blobs in RDBMS or in a distributed file storage system like (S3, Riak & Hadoop). This solution is simple and scalable but has trade-offs:
Second option is a usage of document databases like MongoDb, CouchDb, RethinkDb etc. They fit better (removing some part of hand work) but share some of trade-offs.
Third option ? relational schema ? solves most of the problems and brings new ones :)
But we believe that after solving these problems we will get:
Most of it is required or desired while programming Health IT systems.
PostgreSQL is a powerful, open source object-relational database system. It has more than 15 years of active development and a proven architecture that has earned it a strong reputation for reliability, data integrity, and correctness.
We actively use advanced postgresql features
We code-generate database schema & CRUD views & procedures from FHIR machine readable specification (http://www.hl7.org/implement/standards/fhir/downloads.html). All generation is done in postgresql.
Generation steps:
We heavily use postgresql inheritance for schema infrastructure.
There are two base tables:
Each resource is represented as a root entity table (for example 'patient')
and a table per component (for example: patient.contact is stored in patient_contact
table).
This point is illustrated in the picture below:
Due to inheritance we can access all resources throughout resource table and all resource components by resource_component table.
Base table for all resource aggregate root tables
EATE TABLE resource (
id uuid NOT NULL, -- surrogate resource id
_type varchar , -- real table name (i.e. where data are saved)
_unknown_attributes json, -- json where all unknown attributes will be saved
resource_type character varying, -- resourceType see FHIR documentation
language character varying, -- see FHIR documentation
container_id uuid, -- not null and references aggregating resource if resource is contained
contained_id character varying -- original contained id from resource aggregate
Base table for all resource components
EATE TABLE resource_component (
id uuid NOT NULL, -- surrogate component id
_type character varying NOT NULL, -- real table name
_unknown_attributes json, -- json where all unknown attributes will be saved
parent_id uuid NOT NULL, -- reference to parent component if present
resource_id uuid NOT NULL -- denormalized reference to resource root table, see explanations below
Here is a mapping table for primitive types from FHIR to postgresql:
EATE TABLE type_to_pg_type (
type character varying,
pg_type character varying
PY type_to_pg_type (type, pg_type) FROM stdin;
code varchar
date_time timestamp
string varchar
text text
uri varchar
datetime timestamp
instant timestamp
boolean boolean
base64_binary bytea
integer integer
decimal decimal
sampled_data_data_type text
date date
id varchar
oid varchar
For FHIR system enumerated types we create postgresql ENUMs:
EATE TYPE "AddressUse" AS ENUM (
'home',
'work',
'temp',
'old'
We create table for each compound data type inheriting from resource_component table.
Here is how a table for address type is created:
EATE TABLE address (
use "AddressUse",
text character varying,
line character varying[],
city character varying,
state character varying,
zip character varying,
country character varying
HERITS (resource_component);
For resource attributes with such compound type we create separate tables (for the sake of separation of storage and consistency) and inherit it from type base table:
EATE TABLE organization_address ()
HERITS (address);
Postgresql with default configuration limits length of table names. We didn't want to rebuild postgresql so we shortened table names using the following table of abbreviations:
TE TABLE short_names (name varchar, alias varchar);
RT INTO short_names (name, alias)
ES
('capabilities', 'cap'),
('chanel', 'chnl'),
('codeable_concept', 'cc'),
('coding', 'cd'),
('identifier', 'idn'),
('immunization', 'imm'),
('immunization_recommendation', 'imm_rec'),
('location', 'loc'),
('medication', 'med'),
('medication_administration', 'med_adm'),
('medication_dispense', 'med_disp'),
('medication_prescription', 'med_prs'),
('medication_statement', 'med_st'),
('observation', 'obs'),
('prescription', 'prs'),
('recommendation', 'rcm'),
('resource_reference', 'res_ref'),
('value', 'val'),
('value_set', 'vs')
FHIR allows on level resource ? resource aggregation, see http://www.hl7.org/implement/standards/fhir/references.html.
We save contained resources same way as resources, but in container_id reference to parent resource, and preserve symbolic local resource id in contained_id_ field.
Now resource references are saved as other compound types, but we are looking for a more relational solution for referential integrity and reference traversing.
TODO: we are working on a solution
Relational schema is perfect for querying.
Example ? select patients with recent visits:
CT p.*
OM fhir.encounter_hospitalization_period ehp
JOIN fhir.encounter_subject es
ON es.resource_id = ehp.resource_id
JOIN fhir.patient p
ON p.id = es.reference::uuid
ERE ehp.start BETWEEN LOCALTIMESTAMP ? INTERVAL '1 week' AND LOCALTIMESTAMP
But after searching we want to get the resource entirely (i.e. collect resource aggregate from relational tables).
To simplify this, we generate views with names view
CT vp.id as id, vp.json as resource
OM fhir.encounter_hospitalization_period ehp
JOIN fhir.encounter_subject es
ON es.resource_id = ehp.resource_id
JOIN fhir.view_patient vp
ON vp.id = es.reference::uuid
ERE ehp.start BETWEEN LOCALTIMESTAMP ? INTERVAL '1 week' AND LOCALTIMESTAMP
Manually inserting resource aggregate into relations is also tricky.
To simplify this we generated procedure
insert_resource(_resource json)
which puts resource components
into right relations and return new resource id (uuid).
There are also procedures to delete resources
Update resource is implemented as delete and insert with same id.
TODO: we should think about versioning!
stall postgresql-9.3 and postgresql-contrib
you use debian linux or ubuntu see dev/apt.postgresql.org.sh
sure that SUPERUSER "postgres" is exists
-d postgres -e 'CREATE USER postgres SUPERUSER;'
tap extension is required. You could install it using your favorite packet manager such as homebrew:
install pgtap
ficial guide
://pgtap.org/documentation.html#installation
eate database
-d postgres -e 'create database mydb'`
wnload fhirbase.sql from repository backup and restore using psql
https://raw.github.com/fhirbase/fhirbase/master/fhirbase.sql | psql -d mydb
eck installation
-d mydb -e '\dt fhir.*'
u can install checkout repository,
stall pgtap extension and run tests
clone git@github.com:fhirbase/fhirbase.git
hirbase
-d mydb < fhirbase_test.sql