Skip to content
Navigation

Type at least two characters. Search covers page titles, headings, tags and database names.

↑ ↓ to navigateEnter to openEsc to close0 pages
Elasticsearch and OpenSearchintermediate

Full-Text Search

Query types, relevance scoring, and the difference between filtering and scoring.

3 min readIntermediateUpdated Edit this page

Query context versus filter context

The single most useful distinction: queries score, filters do not. Filters are cacheable and cheaper, so anything that is a yes/no condition belongs in filter.

GET /articles/_search
{
  "query": {
    "bool": {
      "must":   [ { "match": { "body": "database replication" } } ],
      "filter": [
        { "term":  { "status": "published" } },
        { "range": { "published": { "gte": "now-1y" } } }
      ]
    }
  }
}

must contributes to the score. filter only includes or excludes, and its results are cached per segment. Putting a status filter in must makes it slower and changes scores for no benefit.

Query types

QueryUse for
matchStandard full-text search on an analysed field
match_phraseWords in order, adjacent
multi_matchThe same terms across several fields, with per-field weights
term / termsExact value on a keyword field — never on text
rangeNumeric and date ranges
boolCombining the above with must / should / must_not / filter
GET /articles/_search
{
  "query": {
    "multi_match": {
      "query": "postgres vacuum",
      "fields": ["title^3", "body"],
      "type": "best_fields",
      "fuzziness": "AUTO"
    }
  }
}

title^3 weights title matches three times body matches. fuzziness: AUTO tolerates typos with an edit distance scaled to term length.

Relevance

Scoring uses BM25: term frequency, inverse document frequency and field length normalisation.

GET /articles/_search
{
  "explain": true,
  "query": { "match": { "body": "replication lag" } }
}

explain returns the score breakdown per document, which is the only reliable way to understand why one result outranks another.

Adjust relevance with intent rather than by trial and error:

{
  "query": {
    "function_score": {
      "query": { "match": { "body": "replication" } },
      "functions": [
        { "filter": { "term": { "type": "guide" } }, "weight": 2 },
        { "gauss": { "published": { "origin": "now", "scale": "180d", "decay": 0.5 } } }
      ],
      "boost_mode": "multiply"
    }
  }
}

This boosts guides and decays older documents smoothly — the two adjustments most search applications actually need.

Pagination

Highlighting

{
  "query": { "match": { "body": "vacuum" } },
  "highlight": { "fields": { "body": { "fragment_size": 150, "number_of_fragments": 3 } } }
}

Highlighting re-analyses matched documents, so it adds real cost. Limit it to the fields and fragment counts the interface actually displays.