Skip to main content

Queries and Patterns

Fire Arrow Server's GraphQL schema is automatically generated from the FHIR resource definitions. Every FHIR resource type gets three query entry points, each suited to different use cases.

The Three Query Types

For each resource type (using Patient as an example):

QueryPurposeExample
Patient(id: "123")Fetch a single resource by its logical IDDetail views, editing
PatientList(...)Bounded search returning an array of resourcesSimple lists, dropdowns
PatientConnection(...)Cursor-based pagination for large result setsInfinite scroll, paged tables

Single Resource

Fetch one resource by ID:

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d '{
"query": "{ Patient(id: \"123\") { id name { family given } birthDate gender } }"
}'

Response:

{
"data": {
"Patient": {
"id": "123",
"name": [{ "family": "Smith", "given": ["Jane"] }],
"birthDate": "1990-01-01",
"gender": "female"
}
}
}

Bounded List

PatientList returns an array of matching resources. Use search parameters to filter:

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d '{
"query": "{ PatientList(name: \"Smith\", _count: 10) { id name { family given } } }"
}'

Use _offset for simple pagination:

{
PatientList(name: "Smith", _count: 10, _offset: 20) {
id
name { family given }
}
}

Cursor-Based Pagination

PatientConnection provides cursor-based pagination, which is more efficient for large datasets:

{
PatientConnection(name: "Smith", _count: 10) {
count
edges {
node {
id
name { family given }
}
cursor
}
pageInfo {
hasNextPage
hasPreviousPage
}
}
}

To fetch the next page, pass the cursor of the last edge as _cursor:

{
PatientConnection(name: "Smith", _count: 10, _cursor: "WzEyM10=") {
edges {
node { id name { family given } }
cursor
}
pageInfo { hasNextPage }
}
}
Stateless Cursors

Fire Arrow Server uses stateless cursors -- cursor values encode the position directly rather than maintaining server-side state. For this to work correctly, include Cache-Control: no-store in your requests to prevent caching from returning stale cursor pages:

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Cache-Control: no-store" \
-H "Authorization: Bearer <your-token>" \
-d '{"query": "{ PatientConnection(_count: 10) { edges { node { id } cursor } pageInfo { hasNextPage } } }"}'

Search Parameters

Search parameters in GraphQL use underscores instead of the hyphens used in FHIR REST search parameters:

FHIR REST ParameterGraphQL Parameter
general-practitionergeneral_practitioner
birth-datebirth_date
address-cityaddress_city

Special parameters:

ParameterPurpose
_countMaximum number of results to return
_offsetSkip N results (for *List queries)
_cursorResume from cursor (for *Connection queries)
_sortSort field (prefix with - for descending)
_textFull-text search on resource narrative
_contentFull-text search on resource content
Full-Text Search

The _text and _content parameters require full-text search to be enabled in your configuration:

hapi:
fhir:
search_index_full_text_enabled: true

Reference Resolution

One of GraphQL's biggest advantages is resolving FHIR references in a single query. Use the reference field with inline fragments to access the referenced resource:

{
ObservationList(patient: "123") {
id
code { text }
subject {
reference {
resource {
... on Patient {
id
name { family given }
}
}
}
}
}
}

This eliminates the need for follow-up requests to fetch referenced resources -- everything comes back in one response.

Reverse References (Nested Resource Lists)

To fetch resources that reference a given resource (reverse direction), use the *List fields with the _reference parameter:

{
Patient(id: "123") {
id
name { family given }
ObservationList(_reference: "subject") {
id
code { text }
valueQuantity { value unit }
}
ConditionList(_reference: "subject") {
id
code { text }
clinicalStatus { coding { code } }
}
}
}

This fetches a patient along with all their observations and conditions in a single request, using _reference to specify which reference field on the child resource points back to the patient.

Complete Examples

Patient with Observations and Conditions

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d '{
"query": "{ Patient(id: \"123\") { id name { family given } birthDate gender telecom { system value } ObservationList(_reference: \"subject\") { id code { coding { system code display } } valueQuantity { value unit } effectiveDateTime } ConditionList(_reference: \"subject\") { id code { text } clinicalStatus { coding { code } } onsetDateTime } } }"
}'

Practitioner's Patient List with Encounters

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d '{
"query": "{ PatientList(general_practitioner: \"Practitioner/456\", _count: 20, _sort: \"family\") { id name { family given } birthDate EncounterList(_reference: \"subject\", _count: 5, _sort: \"-date\") { id status class { code } period { start end } } } }"
}'

Search with Full-Text and Pagination

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Cache-Control: no-store" \
-H "Authorization: Bearer <your-token>" \
-d '{
"query": "{ PatientConnection(_content: \"diabetes\", _count: 10) { count edges { node { id name { family given } } cursor } pageInfo { hasNextPage } } }"
}'

CarePlan with Activities and Tasks

curl -X POST http://localhost:8080/fhir/\$graphql \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d '{
"query": "{ CarePlan(id: \"789\") { id status subject { reference { resource { ... on Patient { id name { family given } } } } } activity { detail { description scheduledTiming { repeat { frequency period periodUnit } } } } TaskList(_reference: \"based-on\", _sort: \"-authored-on\") { id status code { text } executionPeriod { start end } } } }"
}'