Kosha docs
Documentation menu

Feature

Wildcard queries

A wildcard query expands a pattern against a segment's term dictionary and scores every term that matches. It is how you reach prefixes, suffixes, and infixes that the analyzer does not produce on its own.

POST /v1/namespaces/{namespace}/search
{
  "query_text": "",
  "wildcard": {
    "field": "body",
    "pattern": "notif*",
    "case_insensitive": true
  }
}

Pattern syntax

TokenMeaningExample
*Any run of characters, including nonenotif* → notify, notification
?Exactly one charactergr?y → gray, grey
anything elseMatched literally*breach* → data-breach is not matched; see below

The pattern is matched against indexed terms, not against raw field text. Since the analyzer splits on whitespace and trims only leading and trailing punctuation, a hyphenated string like data-breach is one term — *breach* matches it, breach alone does not. Knowing what your tokens actually look like is most of what makes wildcard queries predictable.

Parameters

pattern string · required
The pattern, with * and ? as above.
case_insensitive bool · default true
Lowercases both sides before matching. Terms are already lowercased at index time, so setting this to false makes an uppercase pattern match nothing rather than making matching stricter in a useful way. Leave it at the default unless you know why you are changing it.
field string · required by the schema
Must be supplied, but does not currently scope the match — the term dictionary is per segment, not per field, so expansion considers terms from every Text field.

Scoring

Expansion happens per segment: the pattern is tested against that segment's terms, and every match becomes a scoring term. A document matching several expanded terms accumulates score from each, so notif* ranks a document containing both notify and notification above one containing only notification.

When wildcard is present it supplies the scoring terms, and query_text is not used. Send the pattern on its own.

Cost

Expansion is a linear scan of the term dictionary in each surviving segment, and every expanded term then costs a postings read. That makes cost proportional to how many terms match, not to how selective the query feels:

  • notif* on a legal corpus expands to a handful of terms — cheap.
  • *a* expands to most of the dictionary — every postings list in the namespace gets read.
  • A leading * defeats nothing structurally here, since the scan is linear either way, but it does tend to expand far wider.

Term-bloom segment pruning does not help a wildcard query: a bloom answers "is this exact term present", and a pattern has no exact term to ask about. A filter alongside the pattern is what restores pruning, because filter blooms are still consulted before the segment opens.

When to reach for something else

If you are using wildcards for prefix autocomplete over a bounded vocabulary, indexing an explicit prefix field — or a Keyword field you can range-filter — will beat a pattern scan by a wide margin, and stays fast as the dictionary grows.