Od Magento 2.4 Elasticsearch jest jedynym wspieranym silnikiem wyszukiwania – MySQL Search został usunięty. Dla wielu sklepów to po prostu „działa”, ale gdy klient zgłasza że „wyszukiwarka nie znajduje właściwych produktów”, zaczyna się prawdziwa praca. Pokazuję jak Magento indeksuje dane w ES, jak debugować zapytania i jak rozszerzyć indeks o własne pola.
Jak Magento indeksuje produkty w Elasticsearch
Magento tworzy w Elasticsearch osobny indeks dla każdego store view, w formacie magento2_product_1 (gdzie 1 to ID store view). Indeks zawiera dokumenty JSON z danymi produktów – atrybuty searchable, filterable i sortable trafiają do odpowiednich pól zgodnie z mappingiem.
Pełna reindeksacja:
# Reindeksacja samego katalogu produktów bin/magento indexer:reindex catalog_product_fulltext # Sprawdzenie stanu indeksera bin/magento indexer:status # Podgląd indeksu bezpośrednio w Elasticsearch curl http://localhost:9200/_cat/indices?v # Sprawdzenie mappingu indeksu Magento curl http://localhost:9200/magento2_product_1/_mapping | python3 -m json.tool
Debugowanie zapytań – co Magento wysyła do ES?
Najprostszy sposób podejrzenia zapytań to włączenie logowania w Elasticsearch i obserwowanie slow query log. Ale szybciej działa bezpośrednie odpytanie ES tym samym zapytaniem co Magento:
<?php
// Własny plugin do logowania zapytań ES - przydatny przy debugowaniu
namespace Vendor\Module\Plugin;
use Magento\Elasticsearch\Model\Adapter\ElasticsearchAdapter;
use Psr\Log\LoggerInterface;
class ElasticsearchQueryLogger
{
public function __construct(
private 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];
}
}
Zapytanie można też skopiować z logów i uruchomić bezpośrednio przez curl aby zobaczyć co Elasticsearch zwraca i jak scoruje dokumenty:
curl -X GET "localhost:9200/magento2_product_1/_search?explain=true" \
-H 'Content-Type: application/json' \
-d '{
"query": {
"bool": {
"must": [
{"match": {"name": {"query": "buty", "boost": 2}}}
],
"filter": [
{"term": {"status": 1}},
{"term": {"visibility": [2, 3, 4]}}
]
}
}
}'
Parametr explain=true zwraca szczegółowe wyjaśnienie jak ES obliczył score dla każdego dokumentu – nieocenione przy debugowaniu „dlaczego ten produkt jest wyżej niż tamten”.
Rozszerzenie indeksu o własne atrybuty
Magento indeksuje w ES atrybuty oznaczone jako Use in Search, Searchable lub Used for Sorting. Możesz też dodać własne dane przez plugin do buildera indeksu:
<?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) {
// Dodaj własne pole do dokumentu ES
// np. liczba sprzedanych sztuk z ostatnich 30 dni
$document['sales_count_30d'] = $this->getSalesCount((int) $productId, 30);
// Pole tekstowe do wyszukiwania po tagach
$document['custom_tags'] = $this->getProductTags((int) $productId);
}
return $documents;
}
private function getSalesCount(int $productId, int $days): int
{
// logika pobierania danych sprzedaży
return 0;
}
private function getProductTags(int $productId): string
{
// logika pobierania tagów
return '';
}
}
Rejestracja pluginu w di.xml:
<?xml version="1.0"?>
<config>
<type name="Magento\Elasticsearch\Model\Adapter\BatchDataMapper\ProductDataMapper">
<plugin name="vendor_module_add_custom_data"
type="Vendor\Module\Plugin\AddCustomDataToIndex"/>
</type>
</config>
Własny analyzer – lepsza obsługa języka polskiego
Domyślna konfiguracja Elasticsearch nie jest optymalna dla języka polskiego. Dodanie analyzera ze stemmerem i stopwordami poprawia jakość wyników:
<?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;
}
}
Po zmianie konfiguracji analyzera konieczna jest pełna reindeksacja – Elasticsearch nie zmienia mappingu istniejącego indeksu, Magento musi go odtworzyć od nowa.
Elasticsearch w DDEV – weryfikacja połączenia
# Sprawdzenie czy ES odpowiada wewnątrz DDEV ddev exec curl -s http://elasticsearch:9200 # Konfiguracja Magento - połącz z ES w kontenerze 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 # Test połączenia przez Magento ddev exec bin/magento config:show catalog/search
Podsumowanie
Elasticsearch w Magento 2 to nie czarna skrzynka – mapowanie indeksu, struktura zapytań i mechanizm scorowania są dostępne i modyfikowalne. Warto zainwestować czas w zrozumienie jak Magento buduje zapytania ES zanim zaczniesz pisać własne rozszerzenia. Parametr explain=true i bezpośrednie odpytywanie ES przez curl to najszybsza droga do zrozumienia „dlaczego wyszukiwarka zwraca złe wyniki”.
