Resource Search Methodologies

You can search FHIR resources using Particle's FHIR API. In general, Particle's API follows the FHIR spec for how searches are performed. However, since there are some distinctions, this guide will show you when and how to use different FHIR search parameters. We've also included examples of the types of searches that our clients use frequently in practice.

If you have any questions about your specific use case and how to search on Particle, reach out to your Particle account team.


Searching by date

Date searches are one of the most common types of searches our customers perform over resources. When working with dates, the following questions are common:

  • How does FHIR handle date searches?
  • Which Particle resources support date searching?
    • Which parameters are supported? (date, effective, or period?)
    • How do these parameters map to the underlying FHIR?

We'll answer these questions with examples below.

How does FHIR handle date searches?

FHIR handles date searching by allowing you to search over dates that are equal to (eq), less than (lt), greater than (gt), greater than or equals to (ge), or less than or equals to a given date (le). FHIR supports all of these search parameters in the form of ={comparator_prefix}YYYY-MM-DD. Specifics on all comparator prefixes can be found here.

  • Date searches are addressed in this section of the FHIR spec.

❗️

For some kinds of resources that support date searching (e.g. the effective date in a MedicationStatement), there may be instances of that resource where there is no available date. In that case, these instances will be excluded from date search results for that resource. This is in line with how the FHIR spec defines how to handle date searches.

To isolate these resources without available dates, use the :missing search modifier. When searching medication statements, for example, chain effective:missing=true to your query.

Date searches using the Particle FHIR API

Below are the Particle resources that support date parameter searches, along with which parameter to use and what each parameter maps to in the underlying FHIR.

Resource nameSearch parameter(s) supportedParameter(s) map to...
AllergyIntoleranceonset and dateOnset period (AllergyIntolerance.reaction.onset) and Recorded date (AllergyIntolerance.recordedDate)
CarePlanactivity-dateActivity date (CarePlan.activity.detail.scheduled)
Compositiondate and periodComposition editing time (Composition.date) and Clinical event date (Composition.event.period)
Conditiononset-dateDate condition began (onsetDateTime)
DiagnosticReportdateEffective period (DiagnosticReport.effective)
EncounterdateEncounter period (Encounter.period)
ImmunizationdateAdministration date (Immunization.occurence)
MedicationStatementeffectiveDate period when the medication was/is/will be taken (MedicationStatement.effective)
ObservationdateObtained date (Observation.effective)
ProceduredateWhen procedure was performed (Procedure.performed)

Example date searches

To show how date searches work with parameters and comparators, let's consider an Encounter where the Encounter.period is the following:

"period": {
    "end": "2021-10-24T00:00:00+00:00",
    "start": "2021-10-19T00:00:00+00:00"
}
  • date=ge2021-10-22&date=lt2021-10-24
    • This date search would return the example Encounter above
  • date=lt2021-10-19
    • This date search would not return the example Encounter above

Resource date fields may include a start and end date value; in this case, the date parameter must be TRUE for at least one for either the start or end date. See examples below:

"period": {
    "end": "2021-09-14T14:18:06+00:00",
    "start": "2021-09-08T00:00:00+00:00"
}
  • date=ge2021-09-08&date=lt2021-09-15
    • This date search would return the example Encounter above
  • date=ge2021-09-08&date=lt2021-09-14 returns the same Encounter
  • date=ge2021-09-09&date=lt2021-09-14 also returns the same Encounter

Finally, here is an Encounter where no end date was provided:

"period": {
    "start": "2021-09-27T00:00:00+00:00"
}
  • date=ge2021-09-09&date=lt2021-09-28
    • This date search would return the Encounter above
  • date=ge2021-09-09&date=lt2021-09-27
    • This date search would not return the Encounter above

Paginating searches and limiting results returned

📘

🔥 See HL7 FHIR Spec

The _count search parameter limits the total number of resources that are returned on a single page. If, for example, a patient has 500 observation resources available, and a client only wants to return 50 observations per page, _count=50 can be added to the search request to apply this to the response:

https://api.particlehealth.com/R4/MedicationStatement/?patient={patient_id}&_count=50

The last element at the bottom of the response will contain a JSON element labeled link. If one of the relation elements in link contains next, this indicates there are more pages as a part of the response. If "relation": "next" is present, copy the url and use it as the next endpoint to query. That will provide the next page of entries. Once there is no "relation": "next" present, there are no more entries or pages to review.

Example:

"link": [
    {
        "relation": "search",
        "url": "search_url"
    },
    **{
        "relation": "next",
        "url": "url_to_return_next_50_resources"
    }**,
    {
        "relation": "first",
        "url": "url_to_first_page"
    },
    {
        "relation": "self",
        "url": "url_to_current_page"
    }
]

❗️

🔥 The maximum number of resources that the API will return per page is 1000. To force the maximum number of resources returned on each query and avoid needing to page through responses (for resource counts under 1000), add _count=1000 to your search.

If over 1000 resources exist, the link array must be used to paginate through all results.

Sorting search results

📘

🔥 See HL7 FHIR spec

The _sort search parameter sorts the bundle of resource requests by three main terms:

  • date: If the resources support date searching, you can return a chronological list of resources by using _sort with the appropriate date search parameter.
    • For example, sorting by the effective period for a MedicationStatement resource would take the _sort=effective search term, while sorting on an Observation date (Observation.effective) would require the _sort=date parameter.
    • Use a minus (-) symbol to return descending results. For example, _sort=date returns the resources in ascending order (from the earliest historical date, going forward), while _sort=-date returns the resources in descending order (from today, going backward in time).
  • status: Using _sort=status will return results ordered by status. Information about statuses can be found in the FHIR spec for each resource. Some examples are:
    • MedicationStatement/Medication/MedicationRequest statuses are active | completed | entered-in-error | intended | stopped | on-hold | unknown | not-taken
    • CarePlan statuses are draft | active | on-hold | revoked | completed | entered-in-error | unknown
    • DiagnosticReport statuses are registered | partial | preliminary | final
  • category: Using _sort=category will return results ordered by category, if the resource has a category. Information about categories can be found in the FHIR spec for each resource. Some examples are:
    • AllergyIntolerance categories are food | medication | environment | biologic
    • Condition categories are problem-list-item | encounter-diagnosis

Searching by code

Codes are used frequently in medicine, for diagnoses, medications, procedures, and more, so it can be quite useful to search over them. FHIR resources can contain one or more codes from different code systems. For example:

  • Medication resources often contain RxNorm and PHIN codes
  • Condition & Observation resources often contain SNOMED and LOINC codes

Searching for specific code within a resource is typically as simple as adding the following parameter to a search:

code={code_of_interest}

For example, if a client is interested in Observation resources that contain lab results for A1c values, they could search for the LOINC code specific to A1c (4548-4) using the following request:

https://api.particlehealth.com/R4/Observation?patient={patient_id}&code=4548-4

That request would search for all Observations that contain a code array that looks like this:

"code": {
    "coding": [
        {
            "code": "4548-4",
            "system": "urn:oid:2.16.840.1.113883.6.1"
        }
    ],
    "text": "Hemoglobin A1C"
}

Within a particular code object, there's a "system" ID, which represents the Object Identifier (OID) for a system. In this case, 2.16.840.1.113883.6.1 is the OID for the LOINC code system. Each code system has a unique OID, but below are some of the most common that we see.

OIDSystem Name
2.16.840.1.113883.6.1LOINC
2.16.840.1.113883.6.69PHIN VADS
2.16.840.1.113883.6.88RxNorm
2.16.840.1.113883.6.90ICD-10
2.16.840.1.113883.6.96SNOMED
2.16.840.1.113883.6.103ICD-9
2.16.840.1.113883.6.208National Drug Data File (NDDF)

To return all codes for a specific code system (e.g. all providers that returned an associated NPI number), use the {search_term}={system}|{code} search methodology (in this case, omitting the code).

Here are a few examples:

code=urn:oid:2.16.840.1.113883.6.88| (all resources with a LOINC code present)

identifier=urn:oid:2.16.840.1.113883.4.1| (all Patient resources with a SSN available)

As mentioned above, most resources that contain some sort of code will support the code search parameter; search terms supported by each resource can be found at the bottom of each resource's FHIR page.

Other useful code system resources can be found below:

❗️

There are scenarios where a non-standard or unknown code is provided by the source EMR. In scenarios where you’re looking for a specific value (e.g. A1c's), string searches may be required to fill in any gaps from your primary code searches.

Below are a few examples of how you may search for an A1c value using the FHIR _content search parameter:

code=UNK&_content=hemoglobin&_content=a1c
code=unknown&_content=hemoglobin&_content=a1c

Searching by resource content and description

📘

🔥 See HL7 FHIR spec

The _content search parameter enables customers to search the content of the resource in its entirety. The _text search parameter enables customers to search the text contained within the resource's narrative.

A resource's narrative is intended to be a human-readable summary of the resource. It will be represented as follows and will contain data — often as freeform text with some HTML styling guidance — that will provide additional context about the resource itself:

"text": {
    "div": "some narrative text",
    "status": "generated"
},

_text example

The following search query could be used to find MedicationStatements that mention "nebulization" for asthma treatment:

https://api.particlehealth.com/R4/MedicationStatement/?patient={patient_id}&_text=nebulization

The result may be a list of MedicationStatement resources that contain a narrative that looks something like this:

"text": {
    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Take 2.5 mg by nebulization 3 (three) times daily.</div>",
    "status": "generated"
}

_content example

Use the _content search parameter to search the entire contents of a particular resource. For example, the following query could be used to find the Composition resource that a MedicationStatement with ID 749f091e-6f15-4741-9e4a-c035f73b2247 came from:

https://api.particlehealth.com/R4/Composition/?patient={patient_id}&_content=749f091e-6f15-4741-9e4a-c035f73b2247

This search query would only return the Composition that contains this MedicationStatement, and nothing else.

Including referenced resources in search results

📘

🔥 See HL7 FHIR spec

Using the _include and _revinclude search parameters, the search results can include other resources that have a reference link to the main result queried. Referencing is common in FHIR: for example, a MedicationStatement can reference Medication resources, or a DiagnosticReport can reference Observation resources.

Using the _include search parameter, the desired child reference will be appended to the response for a GET /:resource (SEARCH) request. This limits the number of consecutive queries that need to be performed. For example, getting the details for all Medication resources within a MedicationStatement can done in one query instead of several by including the Medication resource in a query for the MedicationStatement.

The _revinclude search parameter accomplishes the reverse: it includes the parent reference in the search request. For example, given a Medication resource, _revinclude can be used to find the original MedicationStatement that references the Medication.

From the FHIR spec:

Parameter values for both _include and _revinclude have three parts, separated by a : character:

  • The name of the source resource from which the join comes
  • The name of the search parameter which must be of type reference
  • (Optional) A specific type of target resource (for when the search parameter refers to multiple possible target types)

📘

🔥 The _include parameter also supports wildcard (*) searches. This enables clients to return all resources referenced within the target resource.

https://api.particlehealth.com/R4/Encounter/?patient=](https://api.particlehealth.com/R4/Encounter/?patient=)patient_id&_include=* , for example, will return all referenced Condition , Location, and PractitionerRole resources contained within.

_include example

To include details about every Medication resource referenced within a MedicationStatement resource, the following search query could be used:

https://api.particlehealth.com/R4/MedicationStatement/?patient={patient_id}&_include=MedicationStatement:medication

A sample response is given below. Note that the MedicationStatement resource's search mode is specified as include.

{
    "resourceType": "Bundle",
    "type": "searchset",
    "total": 1,
    "entry": [
        {
            "fullUrl": "https://api.particlehealth.com/R4/MedicationStatement/42a6dd0d-e640-464f-b46c-e8d0a44242fb",
            "resource": {
                "dosage": [
                    {
                        "doseAndRate": [
                            {
                                "doseQuantity": {
                                    "unit": "mg",
                                    "value": 150
                                }
                            }
                        ],
                        "patientInstruction": "Take 150 mg by mouth daily.",
                        "route": {
                            "coding": [
                                {
                                    "code": "C38288",
                                    "display": "Oral",
                                    "system": "urn:oid:2.16.840.1.113883.3.26.1.1"
                                }
                            ],
                            "text": "Oral"
                        }
                    }
                ],
                "id": "a6bf3f31-fd59-4d4a-a4b5-4e9fdb89cee9",
                "identifier": [
                    {
                        "system": "urn:uuid:BBDEFBCA-40CF-11EC-921E-005056BC7C78",
                        "value": "UNK"
                    }
                ],
                "informationSource": {
                    "reference": "PractitionerRole/20800"
                },
                "medicationReference": {
                    "reference": "Medication/d44de379-8b7e-4874-827e-7240c4095575"
                },
                "meta": {
                    "lastUpdated": "2021-11-08T20:12:07.322669+00:00",
                    "versionId": "MTYzNjQwMjMyNzMyMjY2OTAwMA"
                },
                "resourceType": "MedicationStatement",
                "status": "active",
                "subject": {
                    "reference": "Patient/3a8ca478-d6f0-4f2a-96cf-9a704e32502e"
                },
                "text": {
                    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Take 150 mg by mouth daily.</div>",
                    "status": "generated"
                }
            },
            "search": {
                "mode": "match"
            }
        },
        {
            "fullUrl": "https://api.particlehealth.com/R4/Medication/d44de379-8b7e-4874-827e-7240c4095575",
            "resource": {
                "code": {
                    "coding": [
                        {
                            "code": "197319",
                            "system": "urn:oid:2.16.840.1.113883.6.88"
                        },
                        {
                            "code": "0378-0137-01",
                            "system": "urn:oid:2.16.840.1.113883.6.69"
                        },
                        {
                            "code": "203487",
                            "system": "urn:oid:2.16.840.1.113883.6.208"
                        }
                    ],
                    "text": "allopurinol (ZYLOPRIM) 100 mg tablet"
                },
                "id": "0baa7721-ad24-4f6d-817d-6d1d631ac570",
                "meta": {
                    "lastUpdated": "2021-11-08T20:12:07.322669+00:00",
                    "versionId": "MTYzNjQwMjMyNzMyMjY2OTAwMA"
                },
                "resourceType": "Medication"
            },
            "search": {
                "mode": "include"
            }
        }
    ]
}

_revinclude example

To search for Medications of a certain code and the parent MedicationStatement resources associated with them, the following query could be used:

https://api.particlehealth.com/R4/Medication/?code={medication_code}&_revinclude=MedicationStatement:medication

A sample response is given below. Note that the Medication resource's search mode is specified as _revinclude.

{
    "resourceType": "Bundle",
    "type": "searchset",
    "total": 1,
    "entry": [
        {
            "fullUrl": "https://api.particlehealth.com/R4/Medication/74d3504c-0ac3-429e-981e-69608f70fafe",
            "resource": {
                "code": {
                    "coding": [
                        {
                            "code": "391937",
                            "system": "urn:oid:2.16.840.1.113883.6.88"
                        },
                        {
                            "code": "50383-779-31",
                            "system": "urn:oid:2.16.840.1.113883.6.69"
                        },
                        {
                            "code": "568862",
                            "system": "urn:oid:2.16.840.1.113883.6.208"
                        }
                    ],
                    "text": "lactulose (CHRONULAC) 20 gram/30 mL Soln solution"
                },
                "id": "74d3504c-0ac3-429e-981e-69608f70fafe",
                "meta": {
                    "lastUpdated": "2021-11-08T20:12:05.590781+00:00",
                    "versionId": "MTYzNjQwMjMyNTU5MDc4MTAwMA"
                },
                "resourceType": "Medication"
            },
            "search": {
                "mode": "match"
            }
        },
        {
            "fullUrl": "https://api.particlehealth.com/R4/MedicationStatement/f2fd9c0d-4f1e-46f5-b9e5-f1f4b7c5199a",
            "resource": {
                "dosage": [
                    {
                        "doseAndRate": [
                            {
                                "doseQuantity": {
                                    "unit": "g",
                                    "value": 10
                                }
                            }
                        ],
                        "patientInstruction": "Take 10 g by mouth as needed.",
                        "route": {
                            "coding": [
                                {
                                    "code": "C38288",
                                    "display": "Oral",
                                    "system": "urn:oid:2.16.840.1.113883.3.26.1.1"
                                }
                            ],
                            "text": "Oral"
                        }
                    }
                ],
                "id": "f2fd9c0d-4f1e-46f5-b9e5-f1f4b7c5199a",
                "identifier": [
                    {
                        "system": "urn:uuid:ADBBCC76-40CF-11EC-8E28-005056BC7C78",
                        "value": "UNK"
                    }
                ],
                "informationSource": {
                    "reference": "PractitionerRole/20800"
                },
                "medicationReference": {
                    "reference": "Medication/74d3504c-0ac3-429e-981e-69608f70fafe"
                },
                "meta": {
                    "lastUpdated": "2021-11-08T20:12:05.590781+00:00",
                    "versionId": "MTYzNjQwMjMyNTU5MDc4MTAwMA"
                },
                "resourceType": "MedicationStatement",
                "status": "active",
                "subject": {
                    "reference": "Patient/6c9c5478-9313-45f5-aaa0-bdf6c39dc287"
                },
                "text": {
                    "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\">Take 10 g by mouth as needed.</div>",
                    "status": "generated"
                }
            },
            "search": {
                "mode": "include"
            }
        }
    ]
}

And / Or Searches

FHIR also enables implementers to perform and/or searching when trying to find specific values.

OR searches can be performed by separating the parameters by a comma:

  • code=17856-6,4548-4 says find any resource with code 17856-6 OR 4548-4

AND searches can be separated by an &

  • code=4548-4&_content=a1c finds all resources that have both a code equal to 4548-4 AND a1c somewhere in the body of the resource of interest