PHP / Magento Dev Blog

  • Publikacje
  • O autorze
  • Kontakt

Elasticsearch in Magento 2 – indexing, debugging queries, custom analyzer for Polish

by Henryk Tews / Tuesday, 11 August 2020 / Published in Magento 2

Since Magento 2.4 Elasticsearch is the only supported search engine – MySQL Search was removed. For many shops it “just works”, but when a client reports that “the search doesn’t find the right products”, the real work begins. I show how Magento indexes data in ES, how to debug queries, and how to extend the index with custom fields.

How Magento indexes products in Elasticsearch

Magento creates a separate index in Elasticsearch for each store view, in the format magento2_product_1 (where 1 is the store view ID). The index contains JSON documents with product data – searchable, filterable and sortable attributes go into the appropriate fields according to the mapping.

# Full reindex of the product catalogue
bin/magento indexer:reindex catalog_product_fulltext

# Check indexer status
bin/magento indexer:status

# View index directly in Elasticsearch
curl http://localhost:9200/_cat/indices?v

# Check the Magento index mapping
curl http://localhost:9200/magento2_product_1/_mapping | python3 -m json.tool

Debugging queries – what does Magento send to ES?

<?php

// Plugin to log ES queries - useful for debugging
namespace Vendor\Module\Plugin;

use Magento\Elasticsearch\Model\Adapter\ElasticsearchAdapter;

class ElasticsearchQueryLogger
{
    public function __construct(private \Psr\Log\LoggerInterface $logger) {}

    public function beforeQuery(ElasticsearchAdapter $subject, array $query): array
    {
        if (isset($_GET['debug_es'])) {
            $this->logger->debug('ES Query', ['query' => json_encode($query, JSON_PRETTY_PRINT)]);
        }
        return [$query];
    }
}
# Run the query directly against ES to see scoring details
curl -X GET "localhost:9200/magento2_product_1/_search?explain=true" \
  -H 'Content-Type: application/json' \
  -d '{
    "query": {
      "bool": {
        "must": [{"match": {"name": {"query": "shoes", "boost": 2}}}],
        "filter": [
          {"term": {"status": 1}},
          {"terms": {"visibility": [2, 3, 4]}}
        ]
      }
    }
  }'

The explain=true parameter returns a detailed explanation of how ES calculated the score for each document – invaluable when debugging “why is this product ranked higher than that one”.

Extending the index with custom attributes

<?php

namespace Vendor\Module\Plugin;

use Magento\Elasticsearch\Model\Adapter\BatchDataMapper\ProductDataMapper;

class AddCustomDataToIndex
{
    public function afterMap(
        ProductDataMapper $subject,
        array $documents,
        array $documentData,
        int $storeId,
        array $context
    ): array {
        foreach ($documents as $productId => &$document) {
            // Add a custom field to the ES document
            $document['sales_count_30d'] = $this->getSalesCount((int) $productId, 30);
            $document['custom_tags']     = $this->getProductTags((int) $productId);
        }
        return $documents;
    }

    private function getSalesCount(int $productId, int $days): int { return 0; }
    private function getProductTags(int $productId): string { return ''; }
}
<type name="Magento\Elasticsearch\Model\Adapter\BatchDataMapper\ProductDataMapper">
    <plugin name="vendor_module_add_custom_data"
            type="Vendor\Module\Plugin\AddCustomDataToIndex"/>
</type>

Custom analyzer for Polish language

<?php

namespace Vendor\Module\Plugin;

use Magento\Elasticsearch\Model\Adapter\Index\Builder;

class AddPolishAnalyzer
{
    public function afterBuild(Builder $subject, array $settings): array
    {
        $settings['analysis']['analyzer']['polish_analyzer'] = [
            'type'      => 'custom',
            'tokenizer' => 'standard',
            'filter'    => ['lowercase', 'polish_stop', 'polish_stem'],
        ];

        $settings['analysis']['filter']['polish_stop'] = [
            'type'      => 'stop',
            'stopwords' => '_polish_',
        ];

        $settings['analysis']['filter']['polish_stem'] = [
            'type'     => 'stemmer',
            'language' => 'polish',
        ];

        return $settings;
    }
}

After changing the analyzer configuration a full reindex is required – Elasticsearch cannot modify the mapping of an existing index, Magento must recreate it from scratch.

Elasticsearch in DDEV – verifying the connection

# Check if ES is responding inside DDEV
ddev exec curl -s http://elasticsearch:9200

# Configure Magento to connect to ES in the container
ddev exec bin/magento config:set catalog/search/engine elasticsearch7
ddev exec bin/magento config:set catalog/search/elasticsearch7_server_hostname elasticsearch
ddev exec bin/magento config:set catalog/search/elasticsearch7_server_port 9200

Summary

Elasticsearch in Magento 2 is not a black box – the index mapping, query structure and scoring mechanism are all accessible and modifiable. It is worth investing time to understand how Magento builds ES queries before writing your own extensions. The explain=true parameter and direct ES queries via curl are the fastest way to understand “why the search is returning wrong results”.

About Henryk Tews

What you can read next

Strategy pattern in PHP – and how Magento 2 uses it in pricing
Xdebug – configuration, PHPStorm, debugging Magento plugins

© 2026 Created by

TOP
Zarządzaj zgodą
Aby zapewnić jak najlepsze wrażenia, korzystamy z technologii, takich jak pliki cookie, do przechowywania i/lub uzyskiwania dostępu do informacji o urządzeniu. Zgoda na te technologie pozwoli nam przetwarzać dane, takie jak zachowanie podczas przeglądania lub unikalne identyfikatory na tej stronie. Brak wyrażenia zgody lub wycofanie zgody może niekorzystnie wpłynąć na niektóre cechy i funkcje.
Funkcjonalne Always active
Przechowywanie lub dostęp do danych technicznych jest ściśle konieczny do uzasadnionego celu umożliwienia korzystania z konkretnej usługi wyraźnie żądanej przez subskrybenta lub użytkownika, lub wyłącznie w celu przeprowadzenia transmisji komunikatu przez sieć łączności elektronicznej.
Preferencje
Przechowywanie lub dostęp techniczny jest niezbędny do uzasadnionego celu przechowywania preferencji, o które nie prosi subskrybent lub użytkownik.
Statystyka
Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do celów statystycznych. Przechowywanie techniczne lub dostęp, który jest używany wyłącznie do anonimowych celów statystycznych. Bez wezwania do sądu, dobrowolnego podporządkowania się dostawcy usług internetowych lub dodatkowych zapisów od strony trzeciej, informacje przechowywane lub pobierane wyłącznie w tym celu zwykle nie mogą być wykorzystywane do identyfikacji użytkownika.
Marketing
Przechowywanie lub dostęp techniczny jest wymagany do tworzenia profili użytkowników w celu wysyłania reklam lub śledzenia użytkownika na stronie internetowej lub na kilku stronach internetowych w podobnych celach marketingowych.
  • Manage options
  • Manage services
  • Manage {vendor_count} vendors
  • Read more about these purposes
Zobacz preferencje
  • {title}
  • {title}
  • {title}