Optimize Elasticsearch 8 search performance with custom analyzers and field mappings

Advanced 45 min Jun 01, 2026
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Configure custom text analyzers, optimize field mappings, and implement index templates to dramatically improve Elasticsearch search performance and relevance for production workloads.

Prerequisites

  • Elasticsearch 8.x installed and running
  • Basic understanding of Elasticsearch concepts
  • Administrative access to Elasticsearch cluster

What this solves

Elasticsearch performance depends heavily on how you configure text analysis and field mappings. Out-of-the-box settings work for basic use cases, but production search applications need custom analyzers to handle domain-specific text, optimized field mappings to reduce storage overhead, and proper index templates for consistent configuration across indices.

Step-by-step configuration

Install required packages

Install curl and jq for API interactions and JSON processing with Elasticsearch.

sudo apt update
sudo apt install -y curl jq
sudo dnf install -y curl jq

Create custom text analyzers

Configure analyzers for different text processing needs. This example creates analyzers for product search, email processing, and multilingual content.

curl -X PUT "localhost:9200/products_v1" -H "Content-Type: application/json" -d '
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "email_tokenizer": {
          "type": "pattern",
          "pattern": "([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+)"
        }
      },
      "filter": {
        "product_synonym": {
          "type": "synonym",
          "synonyms": [
            "laptop,notebook,computer",
            "mobile,phone,smartphone",
            "tv,television,monitor"
          ]
        },
        "product_stemmer": {
          "type": "stemmer",
          "language": "english"
        },
        "edge_ngram_filter": {
          "type": "edge_ngram",
          "min_gram": 2,
          "max_gram": 20
        }
      },
      "analyzer": {
        "product_search": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "product_synonym",
            "product_stemmer",
            "stop"
          ]
        },
        "product_autocomplete": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "edge_ngram_filter"
          ]
        },
        "email_analyzer": {
          "type": "custom",
          "tokenizer": "email_tokenizer",
          "filter": [
            "lowercase"
          ]
        }
      }
    }
  }
}'

Configure optimized field mappings

Define field mappings that balance search performance with storage efficiency. Use appropriate field types and disable unnecessary features.

curl -X PUT "localhost:9200/products_v1/_mapping" -H "Content-Type: application/json" -d '
{
  "properties": {
    "title": {
      "type": "text",
      "analyzer": "product_search",
      "fields": {
        "autocomplete": {
          "type": "text",
          "analyzer": "product_autocomplete",
          "search_analyzer": "standard"
        },
        "exact": {
          "type": "keyword",
          "ignore_above": 256
        }
      }
    },
    "description": {
      "type": "text",
      "analyzer": "product_search",
      "index_options": "freqs",
      "norms": false
    },
    "category": {
      "type": "keyword",
      "ignore_above": 64
    },
    "tags": {
      "type": "keyword",
      "ignore_above": 32
    },
    "price": {
      "type": "scaled_float",
      "scaling_factor": 100
    },
    "created_at": {
      "type": "date",
      "format": "strict_date_optional_time||epoch_millis"
    },
    "in_stock": {
      "type": "boolean"
    },
    "metadata": {
      "type": "object",
      "enabled": false
    },
    "internal_id": {
      "type": "keyword",
      "index": false
    }
  }
}'

Create index templates for consistency

Index templates ensure all new indices follow the same configuration patterns automatically.

curl -X PUT "localhost:9200/_index_template/products_template" -H "Content-Type: application/json" -d '
{
  "index_patterns": ["products_*"],
  "priority": 100,
  "template": {
    "settings": {
      "number_of_shards": 2,
      "number_of_replicas": 1,
      "refresh_interval": "5s",
      "max_result_window": 50000,
      "analysis": {
        "tokenizer": {
          "email_tokenizer": {
            "type": "pattern",
            "pattern": "([a-zA-Z0-9._-]+@[a-zA-Z0-9._-]+)"
          }
        },
        "filter": {
          "product_synonym": {
            "type": "synonym",
            "synonyms": [
              "laptop,notebook,computer",
              "mobile,phone,smartphone",
              "tv,television,monitor"
            ]
          },
          "product_stemmer": {
            "type": "stemmer",
            "language": "english"
          },
          "edge_ngram_filter": {
            "type": "edge_ngram",
            "min_gram": 2,
            "max_gram": 20
          }
        },
        "analyzer": {
          "product_search": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": [
              "lowercase",
              "product_synonym",
              "product_stemmer",
              "stop"
            ]
          },
          "product_autocomplete": {
            "type": "custom",
            "tokenizer": "standard",
            "filter": [
              "lowercase",
              "edge_ngram_filter"
            ]
          }
        }
      }
    },
    "mappings": {
      "dynamic": "strict",
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "product_search",
          "fields": {
            "autocomplete": {
              "type": "text",
              "analyzer": "product_autocomplete",
              "search_analyzer": "standard"
            },
            "exact": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "description": {
          "type": "text",
          "analyzer": "product_search",
          "index_options": "freqs",
          "norms": false
        },
        "category": {
          "type": "keyword",
          "ignore_above": 64
        },
        "price": {
          "type": "scaled_float",
          "scaling_factor": 100
        },
        "created_at": {
          "type": "date",
          "format": "strict_date_optional_time||epoch_millis"
        }
      }
    }
  }
}'

Optimize search queries

Use specific field targets and appropriate query types to maximize performance with your custom analyzers.

curl -X GET "localhost:9200/products_v1/_search" -H "Content-Type: application/json" -d '
{
  "query": {
    "bool": {
      "should": [
        {
          "match": {
            "title": {
              "query": "laptop computer",
              "boost": 3.0
            }
          }
        },
        {
          "match": {
            "title.autocomplete": {
              "query": "laptop",
              "boost": 2.0
            }
          }
        },
        {
          "match": {
            "description": {
              "query": "laptop computer",
              "boost": 1.0
            }
          }
        }
      ],
      "filter": [
        {
          "term": {
            "in_stock": true
          }
        },
        {
          "range": {
            "price": {
              "gte": 500,
              "lte": 2000
            }
          }
        }
      ]
    }
  },
  "sort": [
    "_score",
    {
      "created_at": {
        "order": "desc"
      }
    }
  ],
  "size": 20
}'

Configure index lifecycle management

Set up ILM policies to automatically manage index performance and storage costs over time.

curl -X PUT "localhost:9200/_ilm/policy/products_policy" -H "Content-Type: application/json" -d '
{
  "policy": {
    "phases": {
      "hot": {
        "actions": {
          "rollover": {
            "max_size": "5gb",
            "max_age": "30d",
            "max_docs": 10000000
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "30d",
        "actions": {
          "set_priority": {
            "priority": 50
          },
          "allocate": {
            "number_of_replicas": 0
          },
          "forcemerge": {
            "max_num_segments": 1
          }
        }
      },
      "cold": {
        "min_age": "90d",
        "actions": {
          "set_priority": {
            "priority": 10
          }
        }
      },
      "delete": {
        "min_age": "365d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}'

Set up monitoring and alerting

Configure monitoring to track search performance metrics and identify optimization opportunities.

# Check cluster health and performance
curl -X GET "localhost:9200/_cluster/health?pretty"
curl -X GET "localhost:9200/_nodes/stats/indices?pretty"

Monitor search performance

curl -X GET "localhost:9200/products_v1/_stats/search?pretty"

Check slow query logs

curl -X PUT "localhost:9200/products_v1/_settings" -H "Content-Type: application/json" -d ' { "index.search.slowlog.threshold.query.warn": "10s", "index.search.slowlog.threshold.query.info": "5s", "index.search.slowlog.threshold.query.debug": "2s", "index.search.slowlog.threshold.fetch.warn": "1s", "index.search.slowlog.threshold.fetch.info": "800ms", "index.search.slowlog.level": "info" }'

Verify your setup

Test your custom analyzers and verify the optimized field mappings are working correctly.

# Test the custom analyzer
curl -X GET "localhost:9200/products_v1/_analyze" -H "Content-Type: application/json" -d '
{
  "analyzer": "product_search",
  "text": "Gaming laptop notebook computer"
}'

Check mapping configuration

curl -X GET "localhost:9200/products_v1/_mapping?pretty"

Verify index template

curl -X GET "localhost:9200/_index_template/products_template?pretty"

Test autocomplete functionality

curl -X GET "localhost:9200/products_v1/_analyze" -H "Content-Type: application/json" -d ' { "analyzer": "product_autocomplete", "text": "laptop" }'

Check index stats and performance

curl -X GET "localhost:9200/products_v1/_stats?pretty&human"

Advanced optimization techniques

Configure search-time boosting

Implement dynamic scoring based on business metrics like popularity, recency, or conversion rates.

curl -X GET "localhost:9200/products_v1/_search" -H "Content-Type: application/json" -d '
{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query": "laptop",
          "fields": ["title^3", "description"]
        }
      },
      "functions": [
        {
          "filter": {
            "range": {
              "created_at": {
                "gte": "now-30d"
              }
            }
          },
          "weight": 1.5
        },
        {
          "field_value_factor": {
            "field": "popularity_score",
            "factor": 1.2,
            "modifier": "log1p",
            "missing": 1
          }
        }
      ],
      "score_mode": "multiply",
      "boost_mode": "multiply"
    }
  }
}'

Implement search result highlighting

Add highlighting to improve search relevance visibility and user experience.

curl -X GET "localhost:9200/products_v1/_search" -H "Content-Type: application/json" -d '
{
  "query": {
    "multi_match": {
      "query": "wireless headphones",
      "fields": ["title", "description"]
    }
  },
  "highlight": {
    "fields": {
      "title": {
        "pre_tags": [""],
        "post_tags": [""],
        "fragment_size": 100,
        "number_of_fragments": 3
      },
      "description": {
        "pre_tags": [""],
        "post_tags": [""],
        "fragment_size": 150,
        "number_of_fragments": 2
      }
    }
  }
}'

Performance monitoring and tuning

Note: Monitor your search performance continuously using the techniques from our Elasticsearch monitoring tutorial to identify bottlenecks and optimization opportunities.

Create a monitoring script to track key performance indicators:

#!/bin/bash

Elasticsearch Performance Monitor

ES_HOST="localhost:9200" LOG_FILE="/var/log/elasticsearch_performance.log" DATE=$(date '+%Y-%m-%d %H:%M:%S') echo "[$DATE] Starting Elasticsearch performance check" >> $LOG_FILE

Check cluster health

HEALTH=$(curl -s "$ES_HOST/_cluster/health" | jq -r '.status') echo "[$DATE] Cluster health: $HEALTH" >> $LOG_FILE

Check search performance

SEARCH_STATS=$(curl -s "$ES_HOST/_nodes/stats/indices/search" | jq '.nodes[] | {query_total: .indices.search.query_total, query_time_in_millis: .indices.search.query_time_in_millis}') echo "[$DATE] Search stats: $SEARCH_STATS" >> $LOG_FILE

Check memory usage

MEMORY_STATS=$(curl -s "$ES_HOST/_nodes/stats/jvm" | jq '.nodes[] | {heap_used_percent: .jvm.mem.heap_used_percent}') echo "[$DATE] Memory usage: $MEMORY_STATS" >> $LOG_FILE

Alert if performance degrades

if [[ "$HEALTH" != "green" ]]; then echo "[$DATE] WARNING: Cluster health is $HEALTH" >> $LOG_FILE # Add alerting logic here fi

Make the script executable and add to cron:

sudo chmod +x /opt/scripts/elasticsearch_performance.sh
echo "/5    * /opt/scripts/elasticsearch_performance.sh" | sudo crontab -

Common issues

SymptomCauseFix
Slow search response timesInefficient analyzers or large result setsOptimize analyzers, use filters instead of queries, implement pagination
High memory usageToo many field mappings or large synonymsUse ignore_above limits, optimize synonym lists, disable unnecessary features
Synonym filter not workingSynonyms applied at wrong stagePlace synonym filter before stemmer in analyzer chain
Autocomplete returning irrelevant resultsEdge n-gram settings too broadAdjust min_gram and max_gram values, use separate search analyzer
Index template not appliedWrong pattern or priority conflictsCheck pattern matching with GET _index_template and adjust priority
Custom analyzer errorsInvalid filter order or configurationTest analyzer with _analyze API, check filter dependencies

Next steps

Running this in production?

Want this handled for you? Running optimized Elasticsearch at scale adds complexity: capacity planning, performance tuning, backup verification, and 24/7 monitoring for search availability. See how we run infrastructure like this for European teams who need search that just works.

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle high availability infrastructure for businesses that depend on uptime. From initial setup to ongoing operations.