--- type: "doc" source: "source/exchanging-search.html" --- \[%settitle Exchanging with FHIR Search%\] \[%file newheader%\] \[%file newnavbar%\] ## Exchanging with FHIR Search | Responsible Owner: [\[%wgt fhir%\]]([%wg fhir%]) Work Group | [Standards Status](versions#std-process):[Informative](versions#std-process) | | --- | --- | This page covers the workflows involved with the various 'search' mechanisms defined for use in FHIR. While the specific URL syntax varies for each of the different query options and, occasionally, the syntax of the response changes, the basics of the workflow is the same regardless of the search mechanism. There are two options: synchronous and asynchronous. ### Synchronous search flow The synchronous search flow is similar to that in basic [FHIR REST](exchanging-rest) operations. The main difference with search is the introduction of [paging](http#paging) to allow large result sets to be retrieved in reasonable-sized chunks. \[%file search-sync.svg %\] 1\. The _data consumer_ uses either a GET - where the search URL defines exactly what retrieval is to be invoked, along with any filters; or with POST - in which case the parameters are passed in the body of the HTTP call. The filters may also include desired page size. The contents of the URL vary by search mechanism, as will the format of response. Some of the search mechanisms may limit to only using GET or POST. The details will be discussed for each approach below. 2\. The search response comes back in the body of the HTTP response. For most search mechanisms, this will be a search-set [Bundle](bundle) containing the results of the search. If no results are found, the result set will be empty, and the HTTP response will still be 200. If the payload is a search-set, the `Bundle.total` will be set to 0. If there was a problem with the format of the search, with permissions or some other error, an appropriate HTTP code will be raised and optionally an [OperationOutcome](operationoutcome) will be provided. The search response will also typically include links that allow navigation of the result set. For search-set Bundles, these will be the 'next', 'previous', 'first' and 'last' URLs conveyed in `Bundle.link`. (Note that only relevant links will be provided and not all servers will support all link types - next and previous are commonly supported; first and last, less so.) 3\. If navigation links were provided, this optional process allows the _data consumer_ to navigate through the pages of the result set. Each new response will include links to navigate from that page. ### Asynchronous search flow Asynchronous search is identical to [RESTful](exchanging-rest#async) and [operation](exchanging-operation#async) asynchronous flows. Not all search approaches will support the asynchronous mechanism (this will be noted below in the section on each approach). Also, not all _data sources_ will support the asynchronous mode, even if it is allowed. In an asynchronous request, there is no paging - all information is included in the file(s) produced by the asynchronous request \[%file rest-async.svg %\] **Step 1:** The invocation of the operation asynchronously is identical to synchronous search invocation, with the exception that the `Prefer` header is set to "respond-async". (Note that the server is not obligated to respect the client's stated preference - it could still respond synchronously.). The response includes a location-header that identifies where to monitor for the progress of the asynchronous operation. **Step 2:** The _data consumer_ [polls](exchanging-polling) the location specified in step 1 to see if the search is complete. So long as it is not, it gets back a 202 Accepted HTTP response, possibly with a message indicating the degree of progress. (Note: At any point, the _data consumer_ could also [cancel](async#3.1.6.3) the request.) **Step 3:** Once the search is complete, the response to the _data consumer_'s polling request changes to a 200 and conveys other information, including URLs to the location of the file (or files) that contain the results of the operation. **Step 4:** The _data consumer_ retrieves the identified file or files from the _data source_, containing the search response. In addition to the [instructions](async) on asynchronous exchange in the base spec, asynchronous search is described in more detail in the [Bulk Data](http://hl7.org/fhir/uv/bulkdata/) implementation guide. Implementers considering asynchronous communication should be familiar with this guide, as the capabilities it requires are much more likely to be widely implemented. ### Approach details Details about workflow differences for each of the search mechanisms are listed below. #### Resource history A [history](http#history) search is always invoked using GET. It can use `[base]/_history`, `[base]/[ResourceType]/_history` or `[base]/[resourceType]/[id]/_history`, depending on whether the desired history is for the whole server, a particular resource type or for a single resource instance. A limited set of parameters are permitted to filter the set of history entries provided and to control the syntax of the response. The response is always a [Bundle](bundle) of type `history`. Paging is supported. #### RESTful search A [RESTful search](search) can be invoked using GET or POST. In the latter case, the parameters are generally sent in the body as application/x-www-form-urlencoded content. However, a mixture where some parameters are on the POST URL and others are in the body is permitted. The base URL for the HTTP call can be either `[base]` or `[base]/[ResourceType]` or `[base]/[resourceType]/[id]/_history` depending on whether the search is across multiple resource types or within a single resource. HL7 defines an extensive set of search parameters to both filter and extend the output. Additional filtering search parameters can also be defined by implementers or other specifications. The response is always a [Bundle](bundle) of type `search-set`. Paging is supported. #### Search using \_filter A [\_filter](search#filter) search is identical to a regular [RESTful search](#search). The only difference is that one of the search parameters included (in the URL or body) is \_filter. #### Search using GraphQL [GraphQL](graphql) works similarly to [RESTful search](#search), but the syntax is different. Both GET and POST are permitted. For both GET and POST, the GraphQL [JSON query string](http://graphql.org/learn/serving-over-http) can be sent as a parameter in the query URL. With POST, it can also be sent in the body, with the ContentType set to `application/graphql`. When using GraphQL, parameters must be exclusively sent in either the URL or the body - they are not permitted to appear in both locations. The base URL for the HTTP call can be one of `[base]/$graphql`, `[base]/[ResourceType]/[id]/$graphql` or `[base]/.../$[operationName]?[parameters]&graphql=...`. The first allows a search against the whole repository. The second starts the search with a specific resource instance. The last allows GraphQL to execute against the results returned by the successful invocation of the operation - be it a resource, a [Parameters](parameters) instance or a search-set Bundle. The operation itself could be one executed at the base, type, or instance level. The response to the search will be custom JSON - defined by the query itself. It can include full-blown resource structures, individual data elements or a combination of both. However, because it is not guaranteed to be FHIR-valid, it is not possible to invoke GraphQL as part of a batch. If the [Connection](graphql#searching) approach is used, then paging is possible. Asynchronous behavior is supported as it is for any FHIR [operation](exchanging-operation#async). #### Search using CQL There is not a formal mechanism for using CQL to perform search defined in the core FHIR specification. However, the draft version of the [Clinical Quality Framework (CQF) IG](http://hl7.org/fhir/uv/cpg) defines a couple of operations allowing data to be retrieved by executing arbitrary CQL. There are two options. The [cpg-cql](http://hl7.org/fhir/uv/cpg/OperationDefinition-cpg-cql.html) operation executes CQL passed directly as an argument. The [cpg-library-evaluate](http://hl7.org/fhir/uv/cpg/OperationDefinition-cpg-library-evaluate.html) operation executes CQL specified in a referenced library. The cpg-cql operation is invoked at the base URL (`[base]/$cql`. It can potentially be invoked using GET if it does not use the `parameters` parameter but can also use POST. The cpg-library-evaluate operation is invoked with the URL `[base]/Library/[id]/$evaluate` can be invoked using GET provided that the `parameters` parameter is not used. It can also be invoked with POST (with parameters past using a [Parameters](parameters) instance). Neither supports paging as the results aren't expected to come back in a search-set [Bundle](bundle). Asynchronous execution is possible as for any FHIR [operation](exchanging-operation#async). #### Search using SPARQL There is no FHIR-specific mechanism for invoking a SPARQL query. The W3C defines a [few](https://www.w3.org/TR/sparql11-protocol/#query-operation) ways to invoke a SPARQL query using a RESTful interface. These mechanisms correspond to the standard GET/POST query flows used for FHIR-defined queries. Other invocation mechanisms are also possible, including the potential use of a FHIR operation. (No standard operation has yet been defined.) Because FHIR search-set [Bundles](bundle) are not involved, there is no query continuation mechanism. It is possible that the FHIR async mechanism could be used when invoking SPARQL, but if so, this would be a custom behavior outside the scope of FHIR - as SPARQL invocation itself is outside the scope of FHIR. #### Search using \_query The [\_query](search#query) mechanism works in a similar manner to [RESTful search](#search). It can be invoked either at the `[base]?_query=name` or `[base]/[resourceType]?_query=name` level. Depending on the nature of the parameters defined by the named operation, it may be possible to invoke it using GET. It can always be invoked using POST - where the body is a [Parameters](parameters) instance. The response (if successful) is a search-set [Bundle](bundle). That bundle may include links that support paging. Asynchronous invocation is supported. \[%file newfooter%\]