Skip to main content

Search Parameters

Ignixa implements comprehensive FHIR search with support for all standard search parameters plus extensible search via FHIR packages.

Package-Based Search Parameters​

Beyond the base FHIR specification parameters, Ignixa can load additional SearchParameter definitions from installed FHIR packages (Implementation Guides). Packages can be installed via:

  • MCP tools - Use install_fhir_package tool via AI assistants
  • Configuration - Pre-load packages at startup (see MCP Server)

This enables:

  • Implementation Guide parameters - US Core, AU Base, UK Core, etc.
  • Custom SearchParameters - Define your own search parameters
  • Custom resource types - Search parameters for StructureDefinitions with custom types

Configuration​

Control how package search parameters are loaded:

{
"SearchParameters": {
"ConflictResolution": {
"PackagePriorityOrder": ["hl7.fhir.us.core", "hl7.fhir.au.base"],
"UseSemanticVersioning": true,
"LogConflicts": true,
"EagerLoadPackageSearchParameters": true
}
}
}
SettingDescription
PackagePriorityOrderPriority when multiple packages define same parameter code
UseSemanticVersioningNewer versions win when no explicit priority
EagerLoadPackageSearchParametersLoad all at startup vs. lazy per resource type

Both loading modes retain inherited base FHIR parameters such as _id, _lastUpdated, and _tag on derived resources alongside package-defined parameters. Package-only resource types such as ViewDefinition also retain these universal Resource parameters alongside their package parameters, including after cache reloads.

When a package parameter declares OverridesUrl, SQL indexing uses the overridden parameter's existing search identity. Re-synchronizing that package, or loading another package, preserves the identity so previously indexed resources remain searchable alongside newly indexed resources. Cold caches reconstruct these aliases from replayed package definitions, including after eviction or restart. Web startup deploys or verifies the SQL schemas and replays conformance events before constructing tenant repositories and their caches. The hosted initializer skips that completed replay. SQL cache initialization still rejects premature access rather than publishing physical IDs that would split the index.

A fresh SQL resource database also seeds the replayed tenant's active package parameters and their storage roots before publishing its reference cache, even when its conformance events are stored in another database. Core catalog seeding preserves those authoritative definitions. The first strict search and first resource write therefore support both overriding and additional package parameters without waiting for a remote activation poll.

Repeated activations of the same canonical and chains of overriding canonicals retain the original storage identity. Replay reconstructs that root from canonical ancestry, validating inherited IDs, including historical self-referencing upgrade events; superseded canonicals keep their root mappings without becoming active search parameters again. SQL synchronization provisions a missing declared root in the same batch rather than temporarily indexing under the overriding parameter's own ID. Unanchored cycles and conflicting inherited identities fail explicitly.

Package activation stages the complete event batch against a detached copy of current conformance state before appending it. Conflicts, including conflicts between parameters in the same package and attempts to move an existing canonical to another storage root, reject the activation without appending events or publishing partial state. Persisted history still undergoes the same identity checks during replay. For multi-instance activation, the SQL event store checks the validated snapshot's global event position under its existing append lock, in the insertion transaction. A concurrent commit rejects the stale activation with CONFORMANCE_CONFLICT; refresh conformance state and retry. The stale proposed batch is never blindly retried.

Multi-instance package activation​

Servers sharing the conformance event store poll for remote activations using Conformance:SyncIntervalSeconds (30 seconds by default). Each instance synchronizes the existing SQL reference caches for its configured tenants and awaits schema invalidation before publishing refreshed search definitions and indexers. It then invalidates tenant capability statements without replaying package imports or terminology side effects.

Event replay and consumer refresh have separate checkpoints. If SQL synchronization or schema/capability invalidation fails after events have been applied, the next poll retries the refresh even when there are no new events. Logs report the applied and successfully refreshed event IDs. Activation does not backfill existing resources; reindex those resources when adding a search parameter.

GET /Patient?family=Smith&given=John

Search Parameter Types​

String​

Case-insensitive, partial match:

GET /Patient?name=smi
GET /Patient?name:exact=Smith
GET /Patient?name:contains=mit
ModifierDescription
(none)Starts with
:exactExact match (case-sensitive)
:containsContains substring

Token​

Coded values with system/code:

# Code only
GET /Observation?code=29463-7

# System|code
GET /Observation?code=http://loinc.org|29463-7

# System only
GET /Observation?code=http://loinc.org|

# Text modifier
GET /Observation?code:text=body%20weight

:::info Token Value Size Limits Token values exceeding database column limits (typically 450 characters) are automatically handled with overflow indexing. Long identifiers, system URIs, and codes remain fully searchable regardless of length. :::

Reference​

Resource references:

# Relative reference
GET /Observation?subject=Patient/123

# Type specified
GET /Observation?subject:Patient=123

# Chaining
GET /Observation?subject.name=Smith

# Identifier
GET /Observation?subject:identifier=http://hospital.org|MRN123

Date/DateTime​

Temporal comparisons:

GET /Observation?date=2024-01-15
GET /Observation?date=ge2024-01-01&date=lt2024-02-01
GET /Patient?birthdate=1990
PrefixMeaning
eqEquals (default)
neNot equals
ltLess than
gtGreater than
leLess than or equal
geGreater than or equal
saStarts after
ebEnds before

Number/Quantity​

Numeric searches:

GET /Observation?value-quantity=gt100
GET /Observation?value-quantity=100||mg
GET /Observation?value-quantity=ge5.4|http://unitsofmeasure.org|mg

URI​

URI matching:

GET /ValueSet?url=http://example.org/ValueSet/my-codes
GET /ValueSet?url:below=http://example.org/

Canonical URIs (used for conformance resources like ValueSet, StructureDefinition) support version-aware matching:

# Match any version of this canonical URL
GET /ValueSet?url=http://example.org/ValueSet/my-codes

# Match specific version only
GET /ValueSet?url=http://example.org/ValueSet/my-codes|1.0.0

# Match versions starting with "1" (prefix match)
GET /ValueSet?url:below=http://example.org/ValueSet/my-codes|1

Canonical search follows FHIR R4 rules:

  • Query url=http://example.org/vs matches resources with that URL (any version) - returns latest
  • Query url=http://example.org/vs|1.0 matches only business version 1.0
  • Query url:below=http://example.org/vs|1 matches versions 1.0, 1.1, 1.2.3, etc.
note

The version in canonical URIs refers to the resource's business version (ValueSet.version), not the server-assigned meta.versionId.

Search Modifiers​

Common Modifiers​

ModifierApplicable TypesExample
:missingAll?birthdate:missing=true
:exactString?name:exact=Smith
:containsString?name:contains=mit
:textToken?code:text=weight
:notToken?status:not=cancelled
:aboveToken, URI`?code:above=http://snomed.info/sct
:belowToken, URI`?code:below=http://snomed.info/sct
:identifierReference?subject:identifier=MRN123
:of-typeToken`?identifier:of-type=http://...

Chained Parameters​

Search on referenced resource properties:

# Single chain
GET /Observation?subject.name=Smith

# Multiple chains
GET /Observation?subject.organization.name=Hospital

# Reverse chain
GET /Patient?_has:Observation:subject:code=29463-7

Combining Chaining with Sorting​

Chained search filters can be combined with _sort to order results by a field on the primary resource:

# Search by chained filter, sort by local field
GET /Observation?subject.name=Smith&_sort=date

# Filter by organization tag, sort by patient family name
GET /Patient?organization._tag=test&_sort=family
note

Sorting by chained parameters (e.g., _sort=subject.birthdate) is not currently supported. The _sort parameter only accepts fields on the primary resource type.

Include/Revinclude​

Return related resources:

# Forward include
GET /Observation?_include=Observation:subject

# Recursive include
GET /Observation?_include:iterate=Observation:subject

# Reverse include
GET /Patient?_revinclude=Observation:subject

Paginated Includes​

Control the number of included resources returned separately from primary matches:

_count limits matching resources, not their includes. If _includesCount is omitted, all resolved includes are returned. Rows fetched only to detect the next match page do not seed _include, _revinclude, or :iterate.

# Limit primary results to 10, includes to 50
GET /Patient?_include=Patient:organization&_count=10&_includesCount=50

# Response contains:
# - Up to 10 patients (primary matches)
# - Up to 50 organizations (included resources)
# - "related" link with _includesContinuationToken if more includes exist
ParameterDescription
_includesCountMaximum number of included resources per page (separate from _count)
_includesContinuationTokenContinuation token for fetching additional included resources

When _includesCount is specified:

  • The Bundle will contain up to _count primary matches
  • The Bundle will contain up to _includesCount included resources
  • If more includes exist, a "related" link is added with _includesContinuationToken
  • Use the $includes operation to fetch additional included resources

Related links retain the original match page, including its after cursor. Follow related links to finish that page's includes; follow next to advance the primary matches. Warnings about unreadable resources remain outcome entries on include continuations and do not consume the _includesCount budget.

See $includes operation for details on fetching additional included resources.

Result Modifiers​

Sorting​

GET /Patient?_sort=birthdate
GET /Patient?_sort=-birthdate # Descending
GET /Patient?_sort=family,given # Multiple

Paging​

GET /Patient?_count=50
GET /Patient?_count=50&_offset=100

Follow the Bundle's next link to continue a search. If stored content cannot be read, the response includes a warning OperationOutcome and omits that resource. A page can therefore contain fewer than _count matches while still having a next link; the link follows the selected database page, not the number of readable resources.

Total Count​

GET /Patient?_total=accurate # Exact count
GET /Patient?_total=estimate # Estimated
GET /Patient?_total=none # No count

Summary​

GET /Patient?_summary=true # Summary only
GET /Patient?_summary=text # Text narrative
GET /Patient?_summary=data # Data only
GET /Patient?_summary=count # Count only

Elements​

GET /Patient?_elements=name,birthDate,gender

Composite Parameters​

Multiple values in conjunction:

GET /Observation?component-code-value-quantity=http://loinc.org|8480-6$gt100

Special Search Parameters​

_not-referenced - Finding Orphaned Resources​

The _not-referenced parameter finds resources that are not referenced by any other resource. This is useful for:

  • Data cleanup workflows
  • Identifying orphaned resources after deletions
  • Data quality audits
  • Compliance reporting

Syntax:

# Find all patients not referenced by any resource
GET /Patient?_not-referenced=*:*

# Find patients not referenced by any Observation
GET /Patient?_not-referenced=Observation:*

# Find patients not referenced by Observation.subject specifically
GET /Patient?_not-referenced=Observation:subject

Patterns:

PatternMeaning
*:*Not referenced by any resource via any reference path
{ResourceType}:*Not referenced by the specified resource type via any path
{ResourceType}:{path}Not referenced via the specific reference path

Implementation Notes:

  • Uses LEFT ANTI-JOIN SQL pattern for optimal performance
  • Only available with SQL storage provider (not in-memory)
  • Compatible with Microsoft FHIR Server syntax

Example Use Cases:

# Find patients without any observations
GET /Patient?_not-referenced=Observation:subject

# Find practitioners not assigned to any organization
GET /Practitioner?_not-referenced=Organization:*

# Find all completely orphaned diagnostic reports
GET /DiagnosticReport?_not-referenced=*:*

Search via POST with _search:

POST /Patient/_search
Content-Type: application/x-www-form-urlencoded

family=Smith&given=John

Search in Bundles​

{
"resourceType": "Bundle",
"type": "batch",
"entry": [{
"request": {
"method": "GET",
"url": "Patient?family=Smith"
}
}]
}

Performance Tips​

  1. Use indexed parameters - Search on indexed fields for best performance
  2. Limit results - Use _count to limit page size
  3. Avoid wildcards - Avoid leading wildcards in string searches
  4. Chain sparingly - Deep chains impact performance