Skip to content
ExponaBLOG
ELASTICSEARCH & SEARCH ENGINEERING · DAY 008 / 100

Analyzers explained in Elasticsearch & Search Engineering

How text becomes searchable terms.

Expona Admin6 min read

When you type a search query into an e-commerce site, you expect to find "running shoes" even if you search for "run shoe." That magic happens inside Elasticsearch analyzers. Analyzers explained in Elasticsearch & Search Engineering reveals how raw text transforms into searchable terms—a process we've debugged countless times across trading platforms, SaaS dashboards, and ride-hailing apps. Understanding analyzers is the difference between a search that feels intelligent and one that frustrates your users.

The analyzer pipeline: Three stages of text transformation

An analyzer is a chain of three sequential components that process text before it's stored in your index. Think of it as an assembly line: raw text enters one end, and out the other comes a set of indexed tokens ready for searching.

The pipeline works like this:

  1. Character filters clean the raw input—removing HTML tags, converting special characters, or normalizing whitespace.
  2. Tokenizer splits the cleaned text into individual tokens, typically by whitespace or punctuation.
  3. Token filters refine those tokens by lowercasing, removing stop words, stemming, or applying synonyms.

Let's work through a real example. Suppose we're indexing a product description: "Premium running shoes—ideal for marathons!" When this text passes through a standard analyzer:

  1. Character filters remove HTML and standardize punctuation.
  2. Tokenizer splits into: Premium, running, shoes, ideal, for, marathons.
  3. Token filters lowercase and remove common stop words like "for," leaving: premium, running, shoes, ideal, marathons.

This final list of tokens is what Elasticsearch actually indexes. When a user searches for "running shoes," Elasticsearch tokenizes that query the same way, then matches it against the indexed tokens. That's how search works at the core.

The standard analyzer: A sensible default

The standard analyzer is Elasticsearch's out-of-the-box choice for most use cases, and for good reason. It handles English and many Western languages well without configuration.

Here's what it does:

  • No character filter (text enters unchanged).
  • Tokenizes on whitespace and punctuation.
  • Lowercases all tokens.
  • Removes 400+ common English stop words (the, a, and, etc.).

If you define a field without specifying an analyzer, Elasticsearch applies the standard analyzer by default:

json
{
  "mappings": {
    "properties": {
      "product_name": {
        "type": "text"
      }
    }
  }
}

In this mapping, product_name uses the standard analyzer automatically. For many e-commerce and SaaS scenarios, this is sufficient. A search for "running shoes" will tokenize to running and shoes, and it will match products with exactly those terms.

However, the standard analyzer has limits. It doesn't handle word variations: a search for "running" won't match "ran" or "runs." That's where language-specific analyzers enter the picture.

Language analyzers: Stemming and morphological understanding

Language analyzers extend the standard analyzer with stemming—a technique that reduces words to their root form. English stemming converts "running," "runs," "ran," and "run" to a common stem, so they match the same search.

Elasticsearch provides dedicated analyzers for English, French, German, Spanish, and many others. The English analyzer, for instance, uses the Porter stemmer algorithm.

Let's configure a field to use the English analyzer:

json
{
  "mappings": {
    "properties": {
      "product_description": {
        "type": "text",
        "analyzer": "english"
      }
    }
  }
}

Now, if your index contains the phrase "I am running in marathons," the English analyzer will produce:

  • Remove stop words: "running," "marathons".
  • Apply stemming: "run," "marathon".

When a user searches for "marathon runner," the query tokenizes to "marathon," "runner," which stems to "marathon," "run." This matches the document, even though the original text was phrased differently.

We've used the English analyzer extensively on travel platforms where users search for trip descriptions. Someone searching for "traveled" will find posts describing "traveling" or "travels." That fuzzy matching dramatically improves discoverability without manual synonym maintenance.

Other languages have their own analyzers. Here's the German analyzer in action:

json
{
  "mappings": {
    "properties": {
      "artikel_text": {
        "type": "text",
        "analyzer": "german"
      }
    }
  }
}

The German analyzer removes German stop words and applies German-specific stemming rules. If your product catalog spans multiple languages, you might index language-specific fields with their corresponding analyzers.

Testing analyzers with the _analyze API

Before indexing thousands of documents, always test your analyzer choice. Elasticsearch exposes the _analyze endpoint, which shows you exactly which tokens an analyzer produces for a given input.

Test the standard analyzer:

json
POST /_analyze
{
  "analyzer": "standard",
  "text": "Running shoes are ideal for marathons!"
}

Response:

json
{
  "tokens": [
    { "token": "running", "start_offset": 0, "end_offset": 7, "type": "", "position": 0 },
    { "token": "shoes", "start_offset": 8, "end_offset": 13, "type": "", "position": 1 },
    { "token": "ideal", "start_offset": 19, "end_offset": 24, "type": "", "position": 2 },
    { "token": "marathons", "start_offset": 29, "end_offset": 38, "type": "", "position": 3 }
  ]
}

Notice that stop words like "are" and "for" are missing, and all tokens are lowercase. Now test the English analyzer on the same text:

json
POST /_analyze
{
  "analyzer": "english",
  "text": "Running shoes are ideal for marathons!"
}

Response:

json
{
  "tokens": [
    { "token": "run", "start_offset": 0, "end_offset": 7, "type": "", "position": 0 },
    { "token": "shoe", "start_offset": 8, "end_offset": 13, "type": "", "position": 1 },
    { "token": "ideal", "start_offset": 19, "end_offset": 24, "type": "", "position": 2 },
    { "token": "marathon", "start_offset": 29, "end_offset": 38, "type": "", "position": 3 }
  ]
}

Observe the stemming: "running" becomes "run," "shoes" becomes "shoe," and "marathons" becomes "marathon." This is the English analyzer's added value.

We rely on _analyze extensively during search tuning. When users report that a search doesn't return expected results, we run _analyze on both the document text and the search query to spot mismatches. Often we discover that the analyzer isn't what we thought, or that stemming is too aggressive for the use case.

Common mistakes

Mismatch between indexing and search analyzers. If you index text with the English analyzer but search with the standard analyzer (or vice versa), tokens won't match. Always verify that both sides use the same analyzer. Elasticsearch applies the field's analyzer to both indexing and queries by default, but you can override this—be careful.

Choosing the wrong analyzer for your language. The standard analyzer is English-centric. If your data is German or French, switch to the language-specific analyzer from day one. Retrofitting thousands of indexed documents is painful.

Over-aggressive stemming. The English analyzer's Porter stemmer sometimes produces odd stems. For instance, "policy" becomes "polici" and "police" becomes "polic"—close but not identical. If exact matching matters (as in legal or medical search), test before committing.

Ignoring stop words in short queries. If a user searches for "the," the standard analyzer strips it, so the query becomes empty. This rarely matters in practice, but on travel or ride-hailing apps where short, precise searches are common, you might want to use a custom analyzer that keeps stop words for short inputs.

Key takeaways

  • Analyzers transform text through three pipeline stages: character filters, tokenizer, and token filters. This is how raw input becomes searchable terms.
  • The standard analyzer is a safe default for English; it lowercases, removes stop words, and tokenizes on punctuation.
  • Language analyzers add stemming, so "running," "runs," and "ran" all match a search for "run."
  • Always test your analyzer choice with the _analyze endpoint before indexing production data.
  • Ensure your indexing and search paths use the same analyzer to avoid silent mismatches.
  • For multilingual indexes, configure language-specific analyzers on the appropriate fields.
ShareXLinkedInReddit

Found this useful? Support the writing.

Buy me a coffee
Written by
Expona Admin
Site administrator

Comments

Loading comments…

Leave a comment

Comments are reviewed before they appear. Be kind and stay on topic.

Related articles