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

import 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

Both query and candidate id flow through _makeKey, which:

  1. Uppercases the input.
  2. 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

A 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?):

CallReturns
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

The 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