More like this query

More like this query #

more_like_this finds documents similar to given text or documents. The engine extracts the input’s terms, keeps the significant ones, and runs the resulting top terms as a disjunctive query — a “find more of this” query without any embedding model.

fields is required and limited to text fields.

How it works #

The query is rewritten at the search entry point — it is a client of the analysis and term pipeline, not an index structure. Per field: gather the like text (free text is analyzed with the first field’s analyzer; a referenced document contributes the text of every query field), tokenize it, drop terms below min_term_freq, outside the word-length bounds, or listed in stop_words, and remove every term the unlike inputs produced. The surviving terms from all fields are pooled, ranked by source term frequency (ties broken alphabetically for determinism), and the top max_query_terms become a bool.should of term queries governed by minimum_should_match. If nothing survives, the query matches nothing. When include is false (the default) and the like input named documents, their ids are added as a must_not — the seed documents trivially contain every selected term.

Input: like and unlike #

like accepts free text strings and document references, mixed in one array; unlike takes the same forms and removes the terms it shares with the selection:

POST /my-collection/_search
{
  "query": {
    "more_like_this": {
      "fields": ["title", "body"],
      "like": [
        "lightweight running shoes",
        { "_id": "42" }
      ],
      "unlike": "clearance sale",
      "min_term_freq": 1,
      "minimum_should_match": "30%"
    }
  }
}
  • Free text is analyzed with the first field’s analyzer.
  • A document reference is { "_id": "<id>" } ("_key" is accepted as an alias). The referenced document’s text is read for term extraction; the document itself is excluded from the results unless include is true.

Parameters #

ParameterDefaultDescription
fields— (required)Text fields to extract terms from and match against.
like— (required)Free text and/or {_id} document references.
unlike—Input whose shared terms are dropped from the selection.
min_term_freq2Ignore terms appearing fewer than this many times in the input.
max_query_terms25Cap on the number of selected terms.
min_doc_freq5Parsed but not applied (see deviations below).
max_doc_freq2147483647Parsed but not applied (see deviations below).
min_word_length0Ignore shorter terms.
max_word_length0 (unlimited)Ignore longer terms.
stop_words—Terms ignored during extraction.
analyzerfield’s analyzerAnalyzer for free-text input.
minimum_should_match"30%"How many selected terms a document must match; percentages truncate (30% of 5 terms → 1).
boost_terms1.0 (off)Boost repeated input terms; activates above 1 (see below).
includefalseWhether the liked documents themselves can match.
boost1.0Query-level boost.

Terms are selected without document frequencies #

The engine expands the query at the search layer, where per-term document frequencies are not yet available, so term selection ranks by input term frequency alone (ties broken alphabetically) and keeps the top max_query_terms.

What this means in practice:

  • min_doc_freq / max_doc_freq are accepted and validated but do not filter. Very common terms (stopword-like tokens that survive the analyzer) can reach the final query — use stop_words or max_word_length to control them instead.
  • Ranking quality relies on the term-frequency cap and minimum_should_match; specificity comes from the analyzer (e.g. a stemming or stop-token analyzer) rather than df filtering.

boost_terms approximation #

The engine multiplies the term’s boost by boost_terms when the value is above one and the term occurred more than once in the input — frequent input terms matter more.

Use cases #

  • “More like this article.” The playground’s free-text form — feed a title or abstract, get the neighbours ranked by shared terms, no embedding model or vector index required.
  • Similar-by-example over stored docs. like: [{ "_id": "A42" }] builds the query from the stored document itself — related-items panels, “variants of this record”, duplicate detection — with the seed document excluded from its own results by default.
  • Steering the neighborhood away. unlike: "clearance sale" drops the boilerplate terms before selection, so similarity is measured on what makes the documents distinct, not their shared template text.
  • Zero-infrastructure similarity. Because selection is pure term statistics, it works on any indexed text field at query time — nothing to train, backfill or keep in sync.
  • match — what MLT compiles down to per term; the bool.should it expands into is ordinary boolean retrieval.
  • bool — the shape of the expansion, including the minimum_should_match knob the selection is governed by.
  • significant_terms — the aggregational cousin: which terms distinguish a foreground set, rather than which documents share a seed’s terms.
Calendar October 7, 2026
Edit Edit this page