Skip to content

sct lexical

Keyword search over the SNOMED CT SQLite database using FTS5 full-text search.

When to use: you know what words to search for. sct lexical "heart attack" returns concepts containing those words. For meaning-based search (when exact words don't match), use sct semantic.


Usage

sct lexical <QUERY|-> [--db <FILE>] [--hierarchy <NAME>] [--limit <N>] [--format text|json|yaml]

Options

Argument / Flag Default Description
<QUERY> (required) Search query. FTS5 syntax: "exact phrase", prefix*, term AND term, etc. Pass - to read one complete query per line from stdin.
--db <FILE> discovered (see Path resolution) SQLite database produced by sct sqlite.
--hierarchy <NAME> (all) Restrict results to a top-level hierarchy (e.g. "Clinical finding").
--limit <N> 10 Maximum number of results.
-f, --format <FORMAT> text Output format: text, json, or yaml.
--ids off Emit only matching SCTIDs (newline-delimited) for piping into other commands; mutually exclusive with an explicit --format.
--template <TEMPLATE> (built-in) Override the per-concept line template (text output only). See sct refset for the variable list.
--template-fsn-suffix <TEMPLATE> (built-in) Override the FSN suffix template (rendered only when the FSN differs from the preferred term).
--provenance / --no-provenance on for TTY, off otherwise Show/hide release provenance (edition, release date) on this query's output.

An empty search exits 0. Text and --ids output leave stdout empty and write the "No results" hint to stderr; structured formats emit an empty collection.


Examples

sct lexical "heart attack"
sct lexical "myocardial infarct*"
sct lexical "heart attack" --hierarchy "Clinical finding"
sct lexical "beta blocker" --limit 20 --db /data/snomed.db

# Pipe matching SCTIDs straight into a code list
sct lexical "asthma" --ids --limit 50 | sct codelist add asthma.codelist -

# JSON output for scripting
sct lexical "heart attack" --format json

# Search several queries and retain their separate result sets
printf '%s\n' 'heart attack' diabetes | sct lexical - --format json

Batch input

Passing - reads each trimmed, nonblank stdin line as a complete query, with a 64 KiB line limit, up to 10,000 entries and 100,000 retained results across the batch. Unlike code-list input, # has no comment meaning here because it may be intentional query text. --limit and --hierarchy apply independently to every query, and input order and duplicates are preserved.

Text and --ids output flatten result sets in query order; --ids cannot be combined with an explicit --format. JSON and YAML emit one document shaped as { "items": [{ "input": "heart attack", "result": [...] }] }; use a structured format when the caller needs to retain query/result boundaries. Every query completes before stdout is written. SQLite applies --limit while FTS5 streams rank order, avoiding a full-result sort; equal-rank rows retain stable FTS index order for a fixed database.


FTS5 query syntax

Syntax Example Matches
Plain terms heart attack Concepts containing both words (implicit phrase)
Exact phrase "heart attack" Concepts containing the exact phrase
Prefix cardio* Concepts with any word starting with "cardio"
Boolean AND heart AND failure Concepts containing both terms
Boolean OR infarct OR infarction Concepts containing either term
Boolean NOT asthma NOT occupational Asthma, excluding occupational variants

Plain text queries (no operators) are automatically quoted to avoid parse errors on special characters. Results are ranked by FTS5 BM25 relevance; equal-rank rows use the FTS index's stable order within a fixed database.


Comparison with sct semantic

sct lexical sct semantic
Basis Keyword matching (FTS5) Meaning / vector similarity
Input SQLite .db Arrow .arrow + Ollama
Speed Instant ~1–2 s (embedding the query)
Finds synonyms Only if indexed Yes
Finds related concepts without shared words No Yes
Works offline Yes Requires local Ollama

Use sct lexical when you know the SNOMED term. Use sct semantic when you're describing a concept in plain language.