Match
Text-to-Concept resolution. Default normalize + exact lookup; replaceable with fuzzy, locale-aware, or server-side matchers.
Match
isa.zyins.medications.match(), isa.zyins.conditions.match(), and
isa.zyins.concepts.match() resolve free text to a single canonical
Concept. The default MatchAlgorithm is _makeKey + exact lookup —
the same normalization the server uses, so the SDK ↔ server identity
holds. Unknown text never throws; it flows through as an UnknownConcept
with inputText preserved.
For a deeper tour of the three accessors and the Concept shape, see
Reference matching. This page documents the
MatchAlgorithm adapter itself.
The MatchAlgorithm interface
MatchAlgorithm interfaceimport type { Concept, UnknownConcept } from 'isa-sdk';
interface MatchAlgorithm {
match(query: string, candidates: readonly Concept[]): Concept | UnknownConcept;
}Implementations MUST be pure and synchronous. Never throw on unknown input; return an UnknownConcept instead.
_makeKey — the default normalization
_makeKey — the default normalizationBoth query and candidate id flow through _makeKey, which:
- Uppercases the input.
- Strips every character that is not ASCII alphanumeric.
So "high blood pressure", "High Blood Pressure!", and
"HIGHBLOODPRESSURE" all normalize to "HIGHBLOODPRESSURE". The
server-side MakeKey does the same thing — that's the parity contract.
Concept | UnknownConcept
Concept | UnknownConceptA successful match returns the canonical Concept:
import type {
ConditionConcept,
MedicationConcept,
ReferenceSort as Sort,
} from 'isa-sdk';
interface Concept {
readonly id: string | null;
readonly name: string;
readonly kind: 'condition' | 'medication' | 'nicotine' | 'unknown';
readonly isKnown: boolean;
readonly inputText: string;
conditions(sort?: Sort): readonly ConditionConcept[];
medications(sort?: Sort): readonly MedicationConcept[];
equals(other: Concept): boolean;
}An UnknownConcept has the same shape with id: null, kind: 'unknown',
isKnown: false, and empty accessors:
import { Isa } from 'isa-sdk';
const isa = await Isa.withBearer();
const unknown = isa.zyins.conditions.match('Postural orthostatic tachycardia syndrome');
unknown.id; // null
unknown.kind; // 'unknown'
unknown.isKnown; // false
unknown.inputText; // 'Postural orthostatic tachycardia syndrome'
unknown.medications(); // []You can still pass this straight into prequalify. The engine canonicalizes
server-side when it can, and treats inputText as raw user input when it
cannot.
Symmetric traversal
Every Concept exposes both medications(sort?) and conditions(sort?):
| Call | Returns |
|---|---|
condition.medications(Sort.MostCommonFirst) | Drugs that treat the condition, prescription-count desc. |
medication.conditions(Sort.MostCommonFirst) | Conditions the drug treats, prescription-count desc. |
condition.medications(Sort.Alphabetical) | Same set, alphabetical asc. |
The accessors read the inline treated_with[] / used_for[] arrays from
the dataset row. Empty until the SDK has fetched the bundle once — call
await isa.zyins.datasets.get() first.
Replacing the matcher
Plug a fuzzy matcher, locale-aware normalizer, or server-side service in at constructor time:
import { Isa, type MatchAlgorithm, type Concept, type UnknownConcept } from 'isa-sdk';
// Your similarity function and unknown-result builder — the two pieces a
// custom matcher supplies. `match` MUST be pure and synchronous, and MUST
// return an UnknownConcept (never throw) on a miss.
declare function trigramSimilarity(a: string, b: string): number;
declare function makeUnknown(query: string): UnknownConcept;
class TrigramMatcher implements MatchAlgorithm {
match(query: string, candidates: readonly Concept[]): Concept | UnknownConcept {
let best: { c: Concept; score: number } | null = null;
for (const c of candidates) {
const s = trigramSimilarity(query, c.name);
if (!best || s > best.score) best = { c, score: s };
}
if (best && best.score >= 0.8) return best.c;
return makeUnknown(query);
}
}
const isa = await Isa.withBearer(undefined, undefined, { matchAlgorithm: new TrigramMatcher() });
const cond = isa.zyins.conditions.match('hyprtension');Substitute when:
- The product needs fuzzy matching (Levenshtein, trigram, embedding).
- The catalog uses a different normalization (locale-aware casefolding, transliteration of Greek/Cyrillic).
- You want to replace the lookup strategy while keeping the traversal accessors (
medications()/conditions()) — they read the bundle's inline rows, not the matcher.
Direct access — isa.zyins.matcher
isa.zyins.matcherThe matcher is exposed as isa.zyins.matcher for callers that want to
match against an arbitrary candidate pool (e.g. a subset filtered by
state):
import { Isa } from 'isa-sdk';
const isa = await Isa.withBearer();
await isa.zyins.datasets.get();
const conditions = isa.zyins.conditions.list();
const cardiac = conditions.filter((c) => c.name.includes('HEART'));
const hit = isa.zyins.matcher.match('chest pain', cardiac);Code samples
TypeScript
import { Isa } from 'isa-sdk';
const isa = await Isa.withBearer();
await isa.zyins.datasets.get();
const hbp = isa.zyins.conditions.match('high blood pressure');
hbp.id; // 'cond_01KSR2WVAGC05ZGR6FA4QYEA8X'
hbp.isKnown; // true
hbp.kind; // 'condition'Python
await isa.zyins.datasets.get()
hbp = isa.zyins.conditions.match('high blood pressure')
print(hbp.id, hbp.is_known, hbp.kind)Go
ctx := context.Background()
isa.Zyins.Datasets.Get(ctx)
hbp := isa.Zyins.Conditions.Match("high blood pressure")
fmt.Println(hbp.ID, hbp.IsKnown, hbp.Kind)PHP
$isa->zyins->datasets->get();
$hbp = $isa->zyins->conditions->match('high blood pressure');
echo $hbp->id, ' ', var_export($hbp->isKnown, true), ' ', $hbp->kind, PHP_EOL;curl
match is an SDK-side operation; there is no dedicated REST endpoint. The
canonical data flows through GET /v3/datasets.
See also
- Reference matching — the three accessors and Concept tour.
- Autocomplete — ranked Suggestion lists.
- Autocorrect — pre-match typo correction.
Updated about 10 hours ago