Skip to content
Jason Walonoski edited this page Apr 24, 2020 · 25 revisions

Search Using the Models

Associate the client with the model:

FHIR::Model.client = client

The FHIR models can now be used to directly interact with a FHIR server.

For example, you can use FHIR::Patient or FHIR::Encounter or any FHIR resource class to directly search using the search method:

# replace FHIR::Model with an actual resource class such as FHIR::Patient or FHIR::MedicationRequest
FHIR::Model.search(parameters)

The FHIR::Model.search method takes in a hash of search parameters (strings as keys, and strings or numbers as values), and on a successful query returns a FHIR::Bundle. On error, the search method throws Exceptions that must be handled.

# search patients
bundle = FHIR::Patient.search(given: 'John', family: 'Doe')
# On success, bundle is a FHIR::Bundle, otherwise an exception is thrown
bundle.each do |resource|
  puts resource.name[0].text
end

If the search is successful, you can use the FHIR::Bundle.each method to iterate over the results (even if they are paginated). See automatically paginating search results or manually paginating search results for more information.

You can also search using dates, date times, references, and any other legal search parameters. For example, to search with dates:

# search encounters by date, greater (or after) April 1st 2020
# GET [base]/Encounter?date=gt2020-04-01
bundle = FHIR::Encounter.search(date: 'gt2020-04-01')

See searching by date and time to see the list of modifiers (e.g. gt is greater than) and other examples.

The remainder of the examples below can be used with FHIR::Model.search by using the appropriate parameters shown in each example.

Search Using the Client

There are several search methods built into the client. The most simple example is the "search" involving no parameters.

client.read_feed(klass, format = nil)

In this case klass is the class representing the FHIR resource type to search, e.g. FHIR::Patient or FHIR::Observation, and format is one of four options:

  • FHIR::Formats::ResourceFormat::RESOURCE_XML
  • FHIR::Formats::ResourceFormat::RESOURCE_JSON
  • FHIR::Formats::ResourceFormat::RESOURCE_XML_DSTU2
  • FHIR::Formats::ResourceFormat::RESOURCE_JSON_DSTU2

Examples:

# using the current default format
reply = client.read_feed(FHIR::Patient)
bundle = reply.resource

# overriding the default format to use XML
reply = client.read_feed(FHIR::Observation, FHIR::Formats::ResourceFormat::RESOURCE_XML)
# print the raw XML of the Bundle
puts reply.body
# use the search result bundle (inflated from the raw XML)
bundle = reply.resource

Automatically Paginating Search Results

Assuming read permissions exist on the resource type, a search result will be returned as a FHIR::Bundle and the resulting entries can be iterated over using the FHIR::Bundle method each.

reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
bundle = reply.resource
bundle.each do |resource|
  puts resource.name[0].text
end
puts reply.code # HTTP 200 (or whatever was returned)
puts reply.body # Raw XML or JSON

Assuming read permissions exist on the resource type, a search result will be returned as a FHIR::Bundle which can be paginated. The FHIR::Bundle instance method each illustrated above, not only iterates through the Bundle entry array, but it will also fetch the next page of results assuming the Bundle contains a "next" link.

Manually Paginating Search Results

As explained above, using the FHIR::Bundle.each instance method will iterate and paginate results, but if you want to paginate manually, you can do so using the FHIR::Bundle.next_bundle method or the FHIR::Client.next_page method.

# next_bundle example
reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
bundle = reply.resource
another_bundle = bundle.next_bundle

# next_page example
reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
bundle = reply.resource
another_reply = client.next_page(reply)

# next_page in a different direction (FOWARD, BACKWARD, FIRST, or LAST)
reply = client.read_feed(FHIR::Patient) # fetch Bundle of Patients
bundle = reply.resource
another_reply = client.next_page(reply, FHIR::Sections::Feed::BACKWARD)

Searching with Parameters

The default search method has the following signature:

def search(klass, options = {}, format = @default_format)
  • klass - the FHIR resource class to search, e.g. FHIR::Patient.
  • options - a Hash of search options described below.
options = {
  :resource => klass,
  :format => format,
  :id => 123, # only use if you are searching by compartment
  :search => {
    :flag => false, # :flag is optional. Search by POST when true, otherwise GET.
    :compartment => 'CompartmentName', # optional searching by compartment
    :parameters => {
      # list of key/value pairs go here
    }
  }
}

Search By Parameter

The name parameter in the following example can be substituted for any combination of parameters as described in http://hl7.org/fhir/R4/search.html including dates, numbers, chaining, and so forth.

# GET [base]/Patient?name=Peter
reply = client.search(FHIR::Patient, search: { parameters: { name: 'Peter' } })
bundle = reply.resource
patient = bundle.entry.first.resource

Search by Date/Time

FHIR date/dateTime searches are documented at http://hl7.org/fhir/R4/search.html#date.

You may need to use the following notation in your search parameters:

  • eq - equal
  • ne - not equal
  • gt - greater than
  • lt - less than
  • ge - greater or equal
  • le - less or equal
  • sa - starts after
  • eb - ends before
  • ap - approximately
# DATE /Encounter?date=gt2020-04-01
client.search(FHIR::Encounter, search: { parameters: { date: 'gt2020-04-01' } })

# DATE using Time
t = Time.now
client.search(FHIR::Encounter, search: { parameters: { date: "eq#{t.to_date.to_s}" } })

# DATETIME /Encounter?date=gt2020-04-01T10:00
client.search(FHIR::Encounter, search: { parameters: { date: 'gt2020-04-01T10:00' } })

# DATETIME using Time
t = Time.now
client.search(FHIR::Encounter, search: { parameters: { date: "gt#{t.iso8601}" } })

# DATE BETWEEN START AND STOP
start = '2020-04-01'
stop = '2020-05-01'
client.search(FHIR::Encounter, search: { parameters: { date: ["gt#{start}", "lt#{stop}"] }})

Search by Reference

# Get an Encounter
reply = client.search(FHIR::Encounter)
bundle = reply.resource
encounter = bundle.entry.first.resource

# Get all Encounters for this subject
client.search(FHIR::Encounter, search: { parameters: { subject: encounter.subject.reference } })

# Get all Observations for a specific encounter
client.search(FHIR::Observation, search: { parameters: { encounter: "Encounter/#{encounter.id}" } })

Search By Compartment

# GET [base]/Patient/123/Condition?code:in=http://hspc.org/ValueSet/acute-concerns
reply = client.search(FHIR::Patient, { id: 123,
                      search: {
                        compartment: 'Condition',
                        parameters: { 'code:in': 'http://hspc.org/ValueSet/acute-concerns' }
                      }})
bundle = reply.resource

Search By URL Encoded POST

# POST [base]/Patient/_search?name=Peter
reply = client.search(FHIR::Patient, search: { flag: true, parameters: { name: 'Peter' } })
bundle = reply.resource
patient = bundle.entry.first.resource

Searching with AND, OR, and Composite Values

Composite value searching is described in http://hl7.org/fhir/R4/search.html#combining

# AND: /Patient?language=FR&language=NL
client.search(FHIR::Patient, search: { parameters: { language: [ 'FR', 'NL' ] } } )

# OR: /Patient?language=FR,NL
client.search(FHIR::Patient, search: { parameters: { language: 'FR,NL' } })

# COMPOSITE: /Group?characteristic-value=gender$mixed
client.search(FHIR::Group, search: { parameters: { 'characteristic-value': 'gender$mixed' } })

Searching Across Resources

FHIR allows you to search on a server across multiple, or all, resource types. See http://hl7.org/fhir/R4/search.html#_type.

In order to execute one of these searches, you need to use the client.search_all method.

def search_all(options = {}, format = @default_format)

Example:

# From the spec:
# GET [base]/?_type=Observation,Condition&other params...
results = client.search_all(search: { parameters: { '_type': 'Observation,Condition' } }
Clone this wiki locally