Configuring Elasticsearch/OpenSearch for Magento 2 Search
Starting from Magento 2.4.0, MySQL search is completely removed from the core — Elasticsearch or OpenSearch are mandatory. Version 2.4.6+ officially supports Elasticsearch 8.x and OpenSearch 2.x. Proper search infrastructure configuration directly impacts conversion: result relevance, response speed, and cluster stability under load.
Version Compatibility
| Magento | Elasticsearch | OpenSearch |
|---|---|---|
| 2.4.3 | 7.10 | — |
| 2.4.4–2.4.5 | 7.16–7.17 | 1.x |
| 2.4.6 | 8.x | 2.x |
| 2.4.7+ | 8.x | 2.x |
OpenSearch is preferred for new projects: Apache 2.0 license, active development, compatible API.
OpenSearch Installation for Production
Recommended approach — Docker or package installation on separate server:
# docker-compose.yml for development
services:
opensearch:
image: opensearchproject/opensearch:2.11.0
environment:
- discovery.type=single-node
- DISABLE_SECURITY_PLUGIN=true
- OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g
ports:
- "9200:9200"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- opensearch-data:/usr/share/opensearch/data
For production cluster minimum — 3 nodes (1 master + 2 data):
# /etc/opensearch/opensearch.yml (data node)
cluster.name: magento-search
node.name: data-node-1
node.roles: [data, ingest]
network.host: 0.0.0.0
discovery.seed_hosts: ["master-node:9300"]
cluster.initial_cluster_manager_nodes: ["master-node"]
path.data: /var/lib/opensearch
path.logs: /var/log/opensearch
# Performance
indices.memory.index_buffer_size: 20%
thread_pool.write.queue_size: 1000
Connecting Magento to OpenSearch
bin/magento config:set catalog/search/engine opensearch
bin/magento config:set catalog/search/opensearch_server_hostname 127.0.0.1
bin/magento config:set catalog/search/opensearch_server_port 9200
bin/magento config:set catalog/search/opensearch_index_prefix magento2
bin/magento config:set catalog/search/opensearch_enable_auth 0
bin/magento config:set catalog/search/opensearch_server_timeout 15
bin/magento indexer:reindex catalogsearch_fulltext
bin/magento cache:flush
Checking index status:
curl -X GET "localhost:9200/_cat/indices/magento2*?v&pretty"
curl -X GET "localhost:9200/magento2_product_1/_mapping?pretty" | head -80
Magento 2 Index Structure
Magento creates index with alias schema: magento2_product_1 (active) and magento2_product_1_v2 (during reindexing). This allows zero-downtime reindex via alias swap.
Custom attribute mapping in index is managed via Magento\Elasticsearch\Model\Adapter\FieldMapper. Custom attributes marked as searchable or filterable are automatically included:
// Custom field mapper for specific types
class CustomFieldMapper extends FieldMapper
{
public function getFieldName($attributeCode, $context = [])
{
if ($attributeCode === 'ean_code') {
return 'keyword_ean_code'; // exact match
}
return parent::getFieldName($attributeCode, $context);
}
}
Relevance and Analyzer Configuration
Default Magento analyzer suits English. For Russian language, morphological analyzer is needed — analysis-icu or analysis-morphology plugin:
# Install plugin for OpenSearch
bin/opensearch-plugin install analysis-icu
# Or for Elasticsearch
bin/elasticsearch-plugin install analysis-icu
Custom analyzer for Russian via index settings:
PUT /magento2_product_1/_settings
{
"analysis": {
"analyzer": {
"russian_search": {
"type": "custom",
"tokenizer": "standard",
"filter": ["lowercase", "russian_stop", "russian_stemmer"]
}
},
"filter": {
"russian_stop": {
"type": "stop",
"stopwords": "_russian_"
},
"russian_stemmer": {
"type": "stemmer",
"language": "russian"
}
}
}
}
Monitoring and Troubleshooting
Key metrics to monitor:
-
Heap usage — no higher than 75% of
-Xmx. OnOutOfMemoryErrorincrease heap or add nodes. - Search latency — p95 < 200ms for product search
- Indexing rate — monitor during bulk product import
# Check cluster health
curl localhost:9200/_cluster/health?pretty
# Slow queries
curl -X PUT "localhost:9200/magento2_product_1/_settings" -H 'Content-Type: application/json' -d'
{
"index.search.slowlog.threshold.query.warn": "2s",
"index.search.slowlog.threshold.query.info": "500ms"
}'
# Magento search query statistics
SELECT query_text, num_results, popularity
FROM search_query
ORDER BY popularity DESC
LIMIT 50;
Common reindex issue: java.lang.IllegalArgumentException: mapper [price_0_1] cannot be changed from type [float] to [double]. Solution — delete and recreate index:
curl -X DELETE "localhost:9200/magento2_product_*"
bin/magento indexer:reindex catalogsearch_fulltext
Setup Timeline
- OpenSearch installation + Magento connection: 1 day
- 3-node cluster setup with replication: 1–2 days
- Custom analyzer tuning + weights for Russian: 2–3 days
- Elasticsearch Suite integration (Smile): 3–5 days







