5.2.1FHIR Searching Basics

 

This page discusses how to use a FHIR endpoint to search for and fetch data. We will enter simple FHIR search queries into the address bar of a web browser.

5.2.2How Searching Works

 

In many ways, the search functionality in FHIR is one of the nicest features for your developers to use. Using a simple RESTful syntax, you can construct both simple and very complex queries, and find all kinds of data in a consistent way.

The mechanics of a FHIR search query are simple:

  1. The client requests data using the following HTTP syntax: GET [baseUrl]/[resourceType]?[optional parameters].
  2. The server then returns a FHIR Bundle resource, which is a container resource containing the matching search results.

This page will give you a taste of the various ways you can search for data. To learn more, visit the FHIR Search page.

5.2.3Basic Searching: Finding Patients

 

The most basic form of a search is a search with no parameters, which matches all resources of a given type. For example, the following search returns all Patients in the system: http://localhost:8000/Patient

You may notice that the response to this query only returns a small number of Patient resources (by default, 50). This is because the server is only returning the first page of results in its initial response. See paging search results below for information about how to fetch subsequent pages.

You can add parameters that narrow your search. The following search query finds any patients with family name "Smith". In this example, we're using the name search parameter. You can find a list of all of the default search parameters in the Search Parameters section at the bottom of the FHIR Patient page. http://localhost:8000/Patient?name=smith

Combine multiple parameters to narrow your search even further (multiple parameters are interpreted as an AND combination). http://localhost:8000/Patient?name=smith&gender=male

Comma-separated values are treated as an OR search (either value may match). For example, the following search query finds people with family name "smith" and a given name of either "stevie" or "elisha". http://localhost:8000/Patient?family=smith&given=stevie,elisha

5.2.4Quantities: Finding Laboratory Values

 

To search Observation resources for lab tests, we have a few options. First, let's use the laboratory category to find all lab tests. For example, the following search query finds all lab tests for the given patient: http://localhost:8000/Observation?subject=Patient/f0e270d7-ed56-4041-9dac-a45a73461c99&category=http://hl7.org/fhir/observation-category|laboratory

If you want to find a specific lab test, you can use the LOINC code for that test and the code search parameter. For example, the following search query finds all Potassium tests (LOINC code 6298-4) across all patients: http://localhost:8000/Observation?code=http://loinc.org|6298-4

We can also add a value-quantity search parameter to find Potassium tests with a specific value. In this example, we're searching for any Potassium tests with a value below 4.0 mmol/L: http://localhost:8000/Observation?code=http://loinc.org|6298-4&value-quantity=lt4.0|http://unitsofmeasure.org/|mmol/L

5.2.5Dates and Times: Narrowing Your Search Window

 

Searching by date in FHIR is quite powerful. Let's start with a simple demonstration. If you want to search for anything matching a date, simply use that date as the search parameter value. For example, here is a search query for any Patients with a given birthday: http://localhost:8000/Patient?birthdate=1941-11-19

Partial dates are okay, too, and they will match any values within the part. For example, the following search finds any Patients born in 1941: http://localhost:8000/Patient?birthdate=1941

Date searches also support a set of qualifiers, which are prefixes on the date that act as a comparator. For example, the value ge2011-01-01 matches any date on or after 2011-01-01. A number of other qualifiers are available under the Date section of the FHIR Search page.

The following search query matches any Encounters for the given patient that started or ended between June 2009 and July 2009. http://localhost:8000/Encounter?subject=Patient/ee2c19c4-ea86-473d-8781-398e4441b5c0&date=ge2009-06-01&date=le2009-07-31

5.2.5.1Last Updated Date

FHIR also supports a special parameter called _lastUpdated that can be used on any resource type. This parameter filters search results to only match resources that were last updated at or after the given date/time (or optionally before).

If the _lastUpdated parameter is specified with a date and time but no timezone, then the server default timezone will be used. If a date value is specified without a time, the search will return resources that have a last updated date that matches the specified date in at least one timezone. For example, if a Patient resource was last updated in Sidney, Australia at 8am, April 15th, 2021, Australia Eastern Standard Time (AEST), then a search for either _lastUpdated=2021-04-15 or _lastUpdated=2021-04-14 will return the Patient resource because 8am on April 15th in AEST timezone would also be 6pm on April 14th in Eastern Daylight timezone.

The _lastUpdated parameter considers the value found in Resource.meta.lastUpdated. It is important to remember that this value is always provided by the server, and clients do not have any control over a resource's last updated date.

To find any Patient resources updated on or after midnight on Jan 1 2017, use the following URL: http://localhost:8000/Patient?_lastUpdated=ge2017-01-01T00:00:00Z

5.2.6Paging Search Results

 

When returning search results, the server will page them by default. Consider the following search query: http://localhost:8000/Observation?code=http://loinc.org|6298-4

This returns a Bundle beginning with the following:

{
  "resourceType": "Bundle",
  "type": "searchset",
  "total": 156,
  "link": [
    {
      "relation": "self",
      "url": "http://localhost:8000/Observation?code=http://loinc.org|6298-4"
    },
    {
      "relation": "next",
      "url": "http://localhost:8000?_getpages=c18f6abf-16e3-41b1-a65b-081b2f6a9642&_getpagesoffset=10&_count=10&_pretty=true&_bundletype=searchset"
    }
  ],
  (...more...)
}

Here we can see that there are 156 matching search results in total. However, the Bundle will only actually contain the first page of results. The URL marked next provides a link to fetch the next page of results. This allows client applications to fetch data in manageable amounts, which improves performance in many cases.

You can control the number of returned results by using the _count parameter: http://localhost:8000/Observation?code=http://loinc.org|6298-4&_count=100

5.2.6.1Search Results Total Count

In the bundle shown above, the total element indicates the full number of available search results.

On a real server this element may or may not be present in your search results. By default, the server will populate this element if it knows the total number of elements that match the given search, but will not populate it if it has not yet determined how many results are matching. For example, if you are searching for Patient?name=smith this might match many thousands of results. The server will return the first page of these results, but it is a potentially slow operation to actually count the remaining results so the server avoids this delay and returns the first page right away.

A client can influence this behaviour by adding an additional _total parameter to your search, e.g. http://localhost:8000/Observation?code=http://loinc.org|6298-4&_count=100&_total=accurate

The server can also cause totals to always be calculated by setting the Default Total Calculation Mode

Be warned, forcing the total to be calculated may cause performance issues! The cost of calculating an accurate total count grows as your data grows, so using this parameter may cause your application to behave well initially, but become unusable as the total amount of data grows. This is especially true for more complex queries. If you are designing a UI with a search results pager, it is often an antipattern to design it in a way that requires an accurate count.

5.2.7Sorting Search Results

 

FHIR makes it easy to sort the results of your search query according to whatever criteria you require.

To sort, simply add the _sort parameter followed by the name of a search parameter. Note that this needs to be the name of a search parameter and not the name of an element in the resource; these are often but not always the same thing.

For example, to search for Patients sorted by family name (ascending and descending shown): http://localhost:8000/Patient?_sort=family
http://localhost:8000/Patient?_sort=-family

You can also sort by multiple search parameters by combining them with a comma: http://localhost:8000/Patient?_sort=family,given

5.2.8Fulltext Searching

 

FHIR includes capabilities for performing a fulltext search across the textual contents of resources. Using the _content parameter, the various textual fields in resources are matched.

For example, the following search query returns all Condition resources that contain the string "diabetes". Note that the search is not case-sensitive. http://localhost:8000/Condition?_content=diabetes

FHIR also provides a second fulltext parameter, _text, which can be used to search across resource Narratives.

5.2.9The Patient $everything Search (Across Patient Chart)

 

FHIR provides a special query known as the $everything operation, which returns all resources associated with a specific patient. In other words, it searches the patient's entire chart.

To invoke this operation on a specific patient, simply invoke the $everything on a Patient resource instance. For example: http://localhost:8000/Patient/1218d9e8-df8d-4f59-b21c-21f5fdff5a00/$everything

Note that in order to avoid overwhelming the client and server, the results of this operation are paged. You will find a link to the next page in the resulting Bundle. You can increase the page size by using the _count parameter, for example: http://localhost:8000/Patient/1218d9e8-df8d-4f59-b21c-21f5fdff5a00/$everything?_count=100

Smile CDR provides an extra parameter on the $everything operation called _content, which performs a fulltext search across the entire patient chart. For example, to search for any resources in the patient's chart containing the term "coronary", invoke the following: http://localhost:8000/Patient/1218d9e8-df8d-4f59-b21c-21f5fdff5a00/$everything?_content=coronary

For more information regarding the $everything command.