## Intro

One of the most basic operations when working with the Medplum FHIR API is to query resources that fulfill certain criteria.

The FHIR specification defines [rich search semantics](https://www.hl7.org/fhir/R4/search.html) to support these use cases, and this guide will cover some of the basic search operations to get you started. If you're new to FHIR, we'd recommend checking out our [FHIR Basics](/content/docs/fhir-basics/index.html) page first.

## Search Parameters

To maintain performance, FHIR doesn't allow Resources to be queried by arbitrary elements. Instead, it defines a set of **search parameters** for each Resource Type.

Let's look at a few examples with the `Patient` resource. The [`Patient` reference docs](/content/docs/api/fhir/resources/patient#search-parameters/index.html) have a table that list out all the available search parameters.

| Search Parameter | Type | Description | Expression |
| --- | --- | --- | --- |
| birthdate | `date` | The patient's date of birth | Patient.birthDate |

Some search parameters, such as `birthdate`, map directly to a top-level element, `Patient.birthDate`. (Note that the search parameter is **all lowercase**, even though the element is camel case)

| Search Parameter | Type | Description | Expression |
| --- | --- | --- | --- |
| address-city | `string` | A city specified in an address | Patient.address.city |

Some search parameters map to nested elements, such as `address-city`, which maps to `Patient.address.city`. Since `Patient.address` is an array element, this search parameter will search _all_ addresses saved to the `Patient`.

| Search Parameter | Type | Description | Expression |
| --- | --- | --- | --- |
| death-date | `date` | The date of death has been provided and satisfies this search value | Patient.deceased |

Lastly, _some_ search parameters rename/alias the target element. For example, the `death-date` maps to the `Patient.deceased` element.

## Basic Search

To search for resources, you can simply add search parameters and values as query parameters in your `GET` request.

The [Medplum Client SDK](/content/docs/sdk/core.medplumclient) also provides the `search` helper method, which accepts a `string` or `object`.

- TypeScript
- cURL

```ts
await medplum.search('Patient', { birthdate: '1940-03-29' });

// OR
await medplum.search('Patient', 'birthdate=1940-03-29');
```

```bash
curl https://api.medplum.com/fhir/R4/Patient?birthdate=1940-03-29
```

This request will return a [FHIR `Bundle`](/content/docs/api/fhir/resources/bundle/index.html) resource, which contains the query results as well as some metadata. The `Bundle.entry` element will contain an array with each `Bundle.entry[i].resource` being a search result.

```ts
// returns
{
  resourceType: 'Bundle',
  type: 'searchset',
  entry: [
    {
      fullUrl: 'http://api.medplum.com/Patient/1',
      resource: {
        resourceType: 'Patient',
        id: '1',
        name: [
          {
            given: ['John'],
            family: 'Doe',
          },
        ],
        birthDate: '1940-03-29',
      },
    },
    {
      fullUrl: 'http://api.medplum.com/Patient/2',
      resource: {
        resourceType: 'Patient',
        id: '2',
        name: [
          {
            given: ['Homer'],
            family: 'Simpson',
          },
        ],
        birthDate: '1940-03-29',
      },
    },
  ],
  link: [
    {
      relation: 'self',
      url: 'http://api.medplum.com/Patient?birthdate=1940-03-29',
    },
  ],
}
```

Because iterating over the `Bundle.entry` array is such a common pattern, the Medplum SDK provides the `searchResources` convenience method that unwraps the bundle and returns an array of resources.

```ts
await medplum.searchResources('Patient', { name: 'Simpson', birthdate: '1940-03-29' });

// OR
await medplum.searchResources('Patient', 'name=Simpson&birthdate=1940-03-29');
```

```ts
// returns
// [
//   {
//     resourceType: 'Patient',
//     id: '2',
//     name: [
//       {
//         given: ['Homer'],
//         family: 'Simpson',
//       },
//     ],
//     birthDate: '1940-03-29',
//   },
// ]
```

The array returned by `searchResources` also includes a `bundle` property that contains the original `Bundle` resource. You can use this to access bundle metadata such as `Bundle.total` and `Bundle.link`.

## Searching Multiple Criteria

You can perform an AND search by specifying multiple query parameters.

- TypeScript
- cURL

```ts
await medplum.searchResources('Patient', { name: 'Simpson', birthdate: '1940-03-29' });

// OR
await medplum.searchResources('Patient', 'name=Simpson&birthdate=1940-03-29');
```

```bash
curl https://api.medplum.com/fhir/R4/Patient?name=Simpson&birthdate=1940-03-29
```

Specifying comma-separated values performs an OR operation for that search parameter.

- TypeScript
- cURL

```ts
await medplum.searchResources('Task', { status: 'completed,cancelled' });

// OR
await medplum.searchResources('Task', 'status=completed,cancelled');
```

```bash
curl https://api.medplum.com/fhir/R4/Task?status=completed,cancelled
```

## Searching by Reference

You can use `reference` search parameters to search for resources based on the resources they refer to.

The syntax for this kind of search is `[parameter]=[resourceType]/[id]`. You can use the [`getReferenceString()`](/content/docs/sdk/core.getreferencestring) utility method to help with construct your query.

For example, to search for all `Observation` resources that reference a `Patient` with the ID `"1234"`:

- TypeScript
- cURL

```ts
/*

curl https://api.medplum.com/fhir/R4/Observation?subject=Patient/1234

*/
const patient: Patient = { resourceType: 'Patient', id: '1234' };
await medplum.searchResources('Observation', { subject: getReferenceString(patient) });

// OR
await medplum.searchResources('Observation', { subject: 'Patient/1234' });
```

```bash
curl https://api.medplum.com/fhir/R4/Observation?subject=Patient/1234
```

## Strings vs. Tokens

FHIR defines two different types of "string" search parameters: `string` and `token`. Their search behaviors are quite different, and it's important to understand the difference.

| `string` | `token` |
| --- | --- |
| Case insensitive<br>Match strings that _start with_ query<br>No `system` URL | Case sensitive<br>_Exact_ string match<br>Optional `system` URL |

### string

A `string` search parameter is used when searching for a specific word or phrase within a resource. This type of search is more general and allows for partial matches, such as searching for patients whose names contain the word "Smith". Searches are **case insensitive**, and any result that **starts with** the query string will be returned.

Example

For example, the following search will return patients with the names `"eve"`, `"Eve"`, `"Evelyn`", but _not_`"Steve"`

`medplum.search('Patient', 'name=eve')`

You can use the `:contains` modifier to search _anywhere_ inside the target string, and the `:exact` modifier to perform a case-sensitive, exact string match (see below)

### token

A `token` search parameter is used when searching for exact matches of a specific code or identifier, such as a medical terminology code ( [`CodeableConcept`](/content/docs/api/fhir/datatypes/codeableconcept/index.html)) or a unique patient identifier ( [`Identifier`](/content/docs/api/fhir/datatypes/identifier/index.html) ). By default, searching a `token` performs a **case-sensitive, exact string match.**

Additionally, many `token` elements are namespaced by a `system` string. This is because FHIR resources often contain codes or identifiers that come from different code systems, such as LOINC or SNOMED CT, which may use the same code or identifier for different concepts.

You can restrict your `token` search to a specific system by using the syntax `<parameter>=<system>|<value>`

Example

The following search would find all patients with _any_ identifier that equals `"12345"`

```ts
medplum.searchResources('Patient', 'identifier=12345');
```

If we only wanted to search for patients whose social security number was `"12345"`, we could use the system string `"http://hl7.org/fhir/sid/us-ssn"` as follows:

```ts
medplum.searchResources('Patient', 'identifier=http://hl7.org/fhir/sid/us-ssn|12345');
```

We can also check for the _presence_ of a particular identifier by dropping the `<value>` and using the syntax `<parameter>=<system>|`.

Example

To find all `Patients` that _have_ a social security number:

```ts
medplum.searchResources('Patient', 'identifier=http://hl7.org/fhir/sid/us-ssn|');
```

## Search Modifiers

The FHIR spec includes a set of **modifiers** to change the way a specific search parameters behave. They are used by appending the string `:<modifier-name>` to the search parameter. While the [FHIR search specification](http://hl7.org/fhir/R4/search.html) details all the available modifiers, we'll describe some of the most common modifiers here.

### `:not`

`:not` excludes the specified values from results.
For example, search for all `Tasks` where status _is not_`completed`:

- TypeScript
- cURL

```ts
await medplum.searchResources('Task', { 'status:not': 'completed' });

//OR
await medplum.searchResources('Task', 'status:not=completed');
```

```bash
curl https://api.medplum.com/fhir/R4/Patient?status:not=completed
```

### `:missing`

`:missing` specifies whether or not to include values where the specified search parameter is present/absent.

For example, searching for all `Patients` with missing `birthDates`.

- TypeScript
- cURL

```ts
await medplum.searchResources('Patient', { 'birthdate:missing': 'true' });

// OR
await medplum.searchResources('Patient', 'birthdate:missing=true');
```

```bash
curl https://api.medplum.com/fhir/R4/Patient?birthdate:missing=true
```

### `:contains`

`:contains` allows you to perform a partial match on `string` search parameters.

For example, searching for `Patients` whose name includes the substring `"stein"`

- TypeScript
- cURL

```ts
await medplum.searchResources('Patient', { 'name:contains': 'eve' });

// OR
await medplum.searchResources('Patient', 'name:contains=eve');
// Return patients with the names `"eve"`, `"Eve"`, `"Evelyn`",  AND `"Steve"`
```

```bash
curl https://api.medplum.com/fhir/R4/Patient?name:contains=eve
```

## Searching by Comparison

FHIR provides a mechanism to search for resources that have a value greater or less than a certain threshold, or that have a value within a specific range, by adding a prefix to your query value. The table below lists the common prefixes used for `quantity`, `number`, and `date` search parameters:

| Prefix | Description |
| --- | --- |
| `eq` | equal |
| `ne` | not equal |
| `gt` | greater than |
| `lt` | less than |
| `ge` | greater than or equal to |
| `le` | less than or equal to |
| `sa` | starts after |
| `eb` | ends before |

This example shows how to find all [`RiskAssessments`](/content/docs/api/fhir/resources/riskassessment/index.html) with a `probability` greater than 0.8.

- TypeScript
- cURL

```ts
await medplum.searchResources('RiskAssessment', { probability: 'gt0.8' });

// OR
await medplum.searchResources('RiskAssessment', 'probability=gt0.8');
```

```bash
curl https://api.medplum.com/fhir/R4/RiskAssessment?probability=gt0.8
```

You can search an inclusive range using an AND search.

- TypeScript
- cURL

```ts
await medplum.searchResources('Observation', [
  ['value-quantity', 'gt40'],
  ['value-quantity', 'lt60'],
]);

// OR
await medplum.searchResources('Observation', 'value-quantity=gt40&value-quantity=lt60');
```

```bash
curl https://api.medplum.com/fhir/R4/Observation?value-quantity=gt40&value-quantity=lt60
```

Note

Because we are specifying the `value-quantity` parameter twice in this query, we must pass a `string[][]` as the second argument to `searchResources()`.

You can search an exclusive range using an OR search.

- TypeScript
- cURL

```ts
await medplum.searchResources('Observation', { 'value-quantity': 'lt40,gt60' });

// OR
await medplum.searchResources('Observation', 'value-quantity=lt40,gt60');
```

```bash
https://api.medplum.com/fhir/R4/Observation?value-quantity=lt40,gt60
```

## Sorting the Results

You can sort your search results by using the special search parameter `_sort`.

The `_sort` parameter allows you specify a list of [search parameters](/content/docs/search/basic-search#search-parameters/index.html) to sort by, in order.

The example below searches for all [`RiskAssessments`](/content/docs/api/fhir/resources/riskassessment/index.html), sorted by their `probability`, then by `date`.

- TypeScript
- cURL

```ts
await medplum.searchResources('RiskAssessment', { _sort: 'probability,date' });

// OR
await medplum.searchResources('RiskAssessment', '_sort=probability,date');
```

```bash
https://api.medplum.com/fhir/R4/RiskAssessment?_sort=probability,date
```

### Reversing the sort order

To sort in _descending_ order, prepend the search parameter with a minus sign `-`. The following example returns [`RiskAssessments`](/content/docs/api/fhir/resources/riskassessment/index.html), in _descending_ order of `probability`:

- TypeScript
- cURL

```ts
await medplum.searchResources('RiskAssessment', { _sort: '-probability' });

// OR
await medplum.searchResources('RiskAssessment', '_sort=-probability');
```

```bash
https://api.medplum.com/fhir/R4/RiskAssessment?_sort=-probability
```

### Sorting by updated time

FHIR also provides the special search parameter, `_lastUpdated`, to search by the last updated time for a resource. The following example searches for the most recently updated [`RiskAssessments`](/content/docs/api/fhir/resources/riskassessment/index.html) resources:

- TypeScript
- cURL

```ts
await medplum.searchResources('RiskAssessment', { _sort: '-_lastUpdated' });

// OR
await medplum.searchResources('RiskAssessment', '_sort=-_lastUpdated');
```

```bash
https://api.medplum.com/fhir/R4/RiskAssessment?_sort=-_lastUpdated
```

## Getting the total number of results

You can use the special search parameter, `_total`, to include the total number of matching resources in your search results. This information is particularly useful for [pagination](/content/docs/search/paginated-search/index.html) and understanding the scope of the data you are dealing with.

## Conclusion

This article covers the basic FHIR search functionality needed to build a healthcare application. The next guides will cover more advanced topics such as paginated search and using GraphQL for retrieving linked Resources.
