Search with _revinclude
_revinclude returns resources that reference your primary matches, in the same Bundle.
Example
Request
curl 'http://localhost/fhir/acme/Patient?identifier=http://hospital.smarthealthit.org%7C1032702&_revinclude=Observation:subject'
Response 200 OK
{
"resourceType": "Bundle",
"id": "8035b6ef-8307-4fd1-848f-3d16ca40543b",
"meta": {
"lastUpdated": "2025-10-10T14:45:06.338-07:00"
},
"type": "searchset",
"total": 48,
"link": [
{
"relation": "self",
"url": "http://localhost:8080/fhir/acme/Patient?_revinclude=Observation%3Asubject&identifier=http%3A%2F%2Fhospital.smarthealthit.org%7C1032702"
}
],
"entry": [
{
"fullUrl": "http://localhost:8080/fhir/acme/Patient/example",
"resource": {
"resourceType": "Patient",
"id": "example",
"meta": {
"versionId": "1",
"lastUpdated": "2025-10-08T17:49:58.037+00:00",
...
},
{
"fullUrl": "http://localhost:8080/fhir/acme/Patient/example-targeted-provenance",
"resource": {
"resourceType": "Patient",
"id": "example-targeted-provenance",
"meta": {
"versionId": "1",
"lastUpdated": "2025-10-08T17:49:58.279+00:00",
...
},
{
"fullUrl": "http://localhost:8080/fhir/acme/Observation/pregnancy-status",
"resource": {
"resourceType": "Observation",
"id": "pregnancy-status",
"meta": {
"versionId": "1",
"lastUpdated": "2025-10-08T17:49:58.299+00:00",
...
},
"search": {
"mode": "include"
}
}
]
}
snippet
In our example, we first find the Patient (by identifier) and then pull in Observations that reference that Patient via Observation.subject.
Parameter syntax
_revinclude={ResourceType}:{searchParamName}
- Observation:subject means “include Observations whose subject references any of the matched Patients”.
- You can specify multiple _revinclude parameters to pull different reverse relationships.
Notes & behavior
- No pagination details here: we’ll cover that on the Pagination page. Practically, _revinclude applies to the current page of primary matches—included resources correspond to those items only.
- De-duplication: included resources are de-duplicated within the Bundle.
- Sorting (_sort) applies to primary matches. Included resources are not sorted relative to primaries.
- Projection:
- _summary and _elements apply to primary results.
- Included resources are typically returned in full by default (unless you also provide _elements, which some servers apply to included entries as well).
- In this beta, return full included resources for clarity.
- Consistency: results reflect only committed documents; no partial/dirty reads.
- Profiles: if the bucket enforces US Core, reverse includes that rely on profile-required references behave consistently (e.g., Observation.subject → Patient).
Performance model (how we do it fast)
- Phase 1: FTS finds primary Patient keys.
- Phase 2: An FTS/term query finds reverse-linked Observations whose subject.reference is any of the Patient IDs (e.g., Patient/123, Patient/abc-uuid…).
- KV fetch assembles the full resources; duplicates are removed.
Example recap (matches your snippet)
Request:
GET /fhir/acme/Patient?identifier=http://hospital.smarthealthit.org|1032702&_revinclude=Observation:subject
Response:
- Bundle.type = "searchset"
- total = < # of matching Patients>
- entry[] contains:
- Patient …,
"search": { "mode": "match" } - Observation …,
"search": { "mode": "include" }
Best practices
- Prefer unique identifiers (e.g., MRN) for the primary search to avoid large result sets.
- Use _count to constrain primary results; we’ll cover pagination on its own page.
- Be explicit about the reference you need (e.g., Observation:subject, Encounter:patient, DocumentReference:patient, etc.).
Under the Hood (How _revinclude is executed)
Goal: return the primary matches plus the reverse-linked resources in a single searchset Bundle—fast, consistent, and deduped.
Execution plan (two-phase gather → one KV fetch)
Phase 1 — Primary keys (FTS)
- Parse search params for the primary type (e.g., Patient?identifier=…).
- Run FTS to get the set of matching document keys (primary keys).
- Buffer these keys in memory (paged if large).
Phase 2 — Secondary keys (FTS)
- For each _revinclude=ResourceType:param, build an FTS query over the referencing field (e.g., Observation.subject.reference in Observation).
- Search for references equal to any of the primary canonical IDs (e.g., Patient/1234, Patient/id).
- Buffer these secondary keys (dedupe as you go).
KV retrieval (batched)
- Concatenate primary + secondary key buffers (after dedupe).
- Perform batched KV gets to fetch full JSON resources in as few round trips as possible.
Assemble the Bundle:
- Primary entries: search.mode = "match"
- Reverse-included entries: search.mode = "include"
Important implementation details
- De-duplication: a resource referenced by multiple primaries appears once in the Bundle.
- Ordering:
- Primary results respect your requested sort (_sort) or server default.
- Included entries are appended (no global sort relative to primaries).
Projection controls:
- We honor _summary / _elements for primary results.
- Included resources are returned in full in beta for clarity (projection of includes can be revisited later).
Isolation & consistency:
- Queries operate at read-committed semantics—only committed docs are returned.
- FTS reflects committed state post-transaction; results are consistent with KV reads at response time.
Memory & safety guards:
- Soft cap on maximum keys per phase (prevents runaway includes).
- Server may truncate secondary include keys if they exceed configured limits and return an OperationOutcome note.
Error handling:
- If a referenced resource goes missing between FTS and KV fetch (rare), we skip it and add an OperationOutcome entry with severity="warning".
Performance knobs:
- Key buffering is chunked; KV gets are batched (size-tuned for your cluster).
- Per-type FTS indexes (or General index) map reference fields as keyword for exact matches.
- Result caching of primary keys enables efficient pagination (covered in the Pagination section).
Why this is fast
- FTS does the set discovery (strings, tokens, dates, references) efficiently.
- KV does the document retrieval in microseconds with batching.
- The split keeps FTS work minimal and pushes bulk I/O to KV where Couchbase shines.