@opencharts/query
v0.0.1
Published
Query utilities for OpenCharts
Downloads
169
Maintainers
Readme
@opencharts/query
Canonical query AST, predicate evaluator, capability registry, and value-set registry.
Overview
@opencharts/query provides the query layer for canonical resources:
CanonicalQuery— typed query object targeting a resource type with an optionalwherepredicate,sort, andlimit.PredicateEvaluator— evaluates a query predicate against a resource instance (catalog-driven type dispatch).CanonicalCapabilityContract/CanonicalCapabilityRegistry— declare and look up what operations a source supports.QueryPlanValidator— validates a query against a capability at plan time (before execution).CanonicalValueSetRegistry— named value sets forin/ninmembership predicates.
Installation
npm install @opencharts/queryUsage
Build a query
import { CanonicalQuery } from '@opencharts/query';
const query = new CanonicalQuery({
target: { resource_type: 'Observation' },
where: {
op: 'and',
operands: [
{ op: 'eq', field: 'code.coding.code', value: '718-7' },
{ op: 'exists', field: 'effective' },
],
},
sort: [{ field: 'effective', direction: 'desc' }],
limit: 10,
});
query.validate(); // throws InvalidCanonicalQueryError if malformedEvaluate a predicate against a resource instance
import { PredicateEvaluator } from '@opencharts/query';
// resources, parameters, valueSets from createCanonicalSystem()
const evaluator = new PredicateEvaluator({ resourceCatalog, parameterCatalog, valueSets });
const matches = evaluator.evaluate(query.where, {
type: 'Observation',
parameters: {
code: { coding: [{ system: 'http://loinc.org', code: '718-7' }] },
effective: '2024-01-15',
},
});
// trueRegister capabilities
import { CanonicalCapabilityRegistry } from '@opencharts/query';
const capabilities = new CanonicalCapabilityRegistry({ resourceCatalog });
capabilities.register({
capability: 'observation.search',
verb: 'search',
resource_type: 'Observation',
query: {
filterable: {
'code.coding.code': ['eq', 'in'],
'effective': ['gt', 'gte', 'lt', 'lte', 'overlaps'],
'subject_ref': ['eq'],
},
sortable: ['effective'],
limit: true,
},
});Validate a query plan
import { QueryPlanValidator } from '@opencharts/query';
const validator = new QueryPlanValidator({ capabilities });
validator.validate(query, 'observation.search');
// Throws UnsupportedCapabilityQueryError if query uses fields/operators the capability doesn't supportValue sets for in / nin
import { CanonicalValueSetRegistry } from '@opencharts/query';
const valueSets = new CanonicalValueSetRegistry();
valueSets.register('active-statuses', ['active', 'in-progress', 'on-hold']);
// Use in a predicate
const predicate = { op: 'in', field: 'status', valueset: 'active-statuses' };Query Operators
| Operator | Type | Shape |
|---|---|---|
| and | logical | { op: 'and', operands: [node, …] } |
| or | logical | { op: 'or', operands: [node, …] } |
| not | logical | { op: 'not', operand: node } |
| exists | presence | { op: 'exists', field } |
| eq / neq | comparison | { op, field, value } or { op, field, input } |
| gt / gte / lt / lte | comparison | same |
| overlaps | period overlap | { op: 'overlaps', field, value } |
| in / nin | membership | { op, field, valueset } or { op, field, values: [] } |
Comparisons over collection fields (e.g. identifiers.value) are existential: true if ANY element satisfies.
API Reference
CanonicalQuery
| Member | Description |
|---|---|
| target | { resource_type, version? } |
| where | Predicate AST node (optional) |
| sort | [{ field, direction? }] |
| limit | Positive integer (optional) |
| validate() | Throws on structural errors |
| leaves() | Returns [{ field, op }] leaf nodes |
PredicateEvaluator
| Method | Description |
|---|---|
| evaluate(predicate, resource) | Returns boolean |
CanonicalCapabilityRegistry
| Method | Description |
|---|---|
| register(contract) | Register a capability contract |
| get(capability) | Returns contract; throws if missing |
| has(capability) | Returns boolean |
| list() | All contracts |
CanonicalValueSetRegistry
| Method | Description |
|---|---|
| register(id, codes) | Register a named code set |
| has(id) | Returns boolean |
| includes(id, code) | Returns boolean; throws if set unknown |
| codes(id) | Returns string[] |
