LifeOmic FHIR Service DSL
LifeOmic FHIR Service DSL(Domain Specific Language) enables you to perform advanced searching and advanced analytics on FHIR resources using the Elasticsearch Query DSL and Elasticsearch Aggregations APIs.
Data Types
The following table shows data type mappings between FHIR and Elasticsearch. All other data types in FHIR compose or extend the data types listed in the table below. Data types that extend the data types listed below are assumed to map to the same Elasticsearch data type unless otherwise noted.
FHIR | Elasticsearch |
---|---|
base64Binary | text / keyword |
boolean | boolean |
date | date |
dateTime | date |
decimal | numeric |
instant | date |
integer | numeric |
string | text / keyword |
time | date |
uri | text / keyword |
Understanding Text and Keyword Data Types
Elasticsearch has two different "string" data types: text
and keyword
.
Each of these data types are useful in different scenarios. text
fields are analyzed and are used to perform full text queries. keyword
fields are used for filtering, sorting and aggregations.
In the LifeOmic FHIR Service DSL, all "string" like fields are represented as both text
and keyword
fields as a multi-field. The root field for every datatype is a text
field and the sub-field "keyword" is a keyword
field.
For example, consider the FHIR Patient identifier.value
field:
In the FHIR schema, this field is a string
data type. In LifeOmic FHIR Service DSL this field exists as identifier.value
as a text
datatype and as identifier.value.keyword
as a keyword
datatype.
The DSL Language
LifeOmic FHIR Service DSL is a SQL AST (Abstract Syntax Tree) and super-set of the Elasticsearch Query DSL and Elasticsearch Aggregations APIs.
Select Statement
Retrieves all FHIR resources from the targeted table.
JMES Path | Definition | Optional |
---|---|---|
type | "select" | |
columns | "*" or an Object Identifier | |
from | A Table Identifier | |
where | A Where Clause | Yes |
orderby | An Order-By Clause | Yes |
limit | A Limit Clause | Yes |
Examples
Get all Patient resources
{
"type": "select",
"columns": "*",
"from": [
{
"table": "patient"
}
]
}
Get all Patient resource id
values
{
"type": "select",
"columns": [
{
"expr": {
"type": "column_ref",
"column": "id.keyword"
}
}
],
"from": [
{
"table": "patient"
}
]
}
Object Identifier
JMES Path | Definition |
---|---|
[*] | One or more Column Identifiers |
or
JMES Path | Definition |
---|---|
[0].type | "elasticsearch" |
[0].aggregations | An Elasticsearch Aggregation |
Examples
Identify multiple columns
[
{
"expr": {
"type": "column_ref",
"column": "id.keyword"
}
},
{
"expr": {
"type": "column_ref",
"column": "effectiveDateTime"
}
}
]
Count the number of id
values
[
{
"type": "elasticsearch",
"aggregations": {
"results": {
"value_count": {
"field": "id.keyword"
}
}
}
}
]
Estimate the number of subject.reference
values
[
{
"type": "elasticsearch",
"aggregations": {
"results": {
"cardinality": {
"field": "subject.reference.keyword"
}
}
}
}
]
Column Identifier
JMES Path | Definition |
---|---|
expr.type | "column_ref" |
expr.column | A FHIR resource field name |
Table Identifier
A table identifer is a FHIR resources type written in snake_case. For example, DiagnosticReport
becomes disagnostic_report
.
JMES Path | Definition |
---|---|
[0].table | A FHIR resource name |
Where Clause
JMES Path | Definition |
---|---|
type | "elasticsearch" |
query | An Elasticsearch Query DSL |
highlight | An Elasticsearch Highlighter |
Examples
Filter where the gender
is "male"
{
"type": "elasticsearch",
"query": {
"term": {
"gender.keyword": "male"
}
}
}
Filter where the valueInteger
is greater than 10
{
"type": "elasticsearch",
"query": {
"range": {
"valueInteger": {
"gt": 10
}
}
}
}
Highlight the Diagnostic Report subject.reference
{
"type": "select",
"columns": "*",
"from": [
{
"table": "diagnostic_report"
}
],
"where": {
"type": "elasticsearch",
"query": {
"bool": {
"must": {
"match": {
"text.div": "important"
}
}
}
},
"highlight": {
"fields": {
"text.div": {}
}
}
}
}
Order-By Clause
JMES Path | Definition |
---|---|
[*].type | ASC or DESC |
[*].expr | A Column Identifier |
Examples
Order results by the id.keyword
field
{
[
{
"type": "ASC",
"expr": {
"type": "column_ref",
"column": "id.keyword"
}
}
]
}
Limit Clause
JMES Path | Definition |
---|---|
[0].type | "number" |
[0].value | The offset as a nonnegative numeric integer |
[1].type | "number" |
[1].value | The limit as a nonnegative numeric integer |
or
JMES Path | Definition |
---|---|
[0].type | "elasticsearch" |
[0].search_after | An Elasticsearch Search After clause |
[1].type | "number" |
[1].value | The limit as a nonnegative numeric integer |
Note: A Search-After clause must be used in conjunction with an Order By Clause
Examples
Limit the result to 100 results
[
{
"type": "number",
"value" 0
},
{
"type": "number",
"value" 100
}
]
Get results 11 through 20
[
{
"type": "number",
"value" 10
},
{
"type": "number",
"value" 10
}
]
Get the next 10 results after "50619f8c-10aa-464a-a227-90a7aa6ffd43"
[
{
"type": "elasticsearch",
"search_after": [
"50619f8c-10aa-464a-a227-90a7aa6ffd43"
]
},
{
"type": "number",
"value" 10
}
]
Scrolling
When using scrolling, the limit clause is only recognized for the initial request. For each subsequent request, the limit is duplicated and the offset is automatically adjusted. Altering the limit clause will have no effect.
For example, if the offset and limit are set to 0 and 100, the first request will return the first 100 results (1 - 100), and the next request will return the next 100 results (101 - 200).
Scrolling is not compatible with the Elasticsearch Search-After clause.
Response
The response is a standard Elasticsearch Search Response Body. The following is a breakdown of the individual fields in the object described using JMES Path notation.
JMES Path | Definition |
---|---|
took | The amount of time it took the server to respond. |
timed_out | true if the server timed out, false otherwise. |
shards | An overview of the shards scanned. |
shards.total | The number of shards scanned. Additional shards can be requested by contacting LifeOmic. |
shards.successful | The number of shards scanned successfully. |
shards.skipped | The number of shards skipped. |
shards.failed | The number of shards scanned that failed. |
hits | An overview of the FHIR resources found. |
hits.total | The total number of FHIR resources found during scanning. |
hits.total.value | The total number of FHIR resources found during scanning. |
hits.total.relation | eq if hits.total is less than 10,000, gte otherwise. |
hits.max_score | The maximum relative relevancy. |
hits.hits | The resources returned. |
hits.hits[*]._index | The index the FHIR resources belong to. |
hits.hits[*]._type | Always _doc . |
hits.hits[*]._id | A Base64 encoded Resource LRN. |
hits.hits[*]._score | The FHIR resource relevancy. |
hits.hits[*]._source | The FHIR resource, whose schema matches the official FHIR schema defined by the FHIR specification. A full list of FHIR resources can be found at the FHIR Resource List. |
aggregations | The aggregation results. See the Elasticsearch Aggregations documentation for additional information. |