Wolne wyszukiwanie w PrestaShop: przyczyny, filtry, pomiar

autor: Presta365 Poradniki techniczne

Moduł do tego problemu

Wyszukiwarka Elasticsearch i nawigacja fasetowa

Wyszukiwanie na wbudowanym silniku lub z Elasticsearch, OpenSearch i Meilisearch, tolerancja literówek, filtry fasetowe i analiza wyszukiwań bez wyników. Instaluje się go z wbudowanym silnikiem, a silnik zewnętrzny podłącza się, gdy jest potrzebny. PrestaShop 1.7.7, 8 i 9, 12 miesięcy aktualizacji w cenie, potem odnowienie jest opcjonalne.

Zobacz modułPrzeczytaj poradnikWypróbuj demo

Jak działa natywne wyszukiwanie PrestaShop

Zweryfikowano w kodzie PrestaShop 9.1.5 (classes/Search.php) oraz modułu ps_facetedsearch 5.0.0; pliki są w źródłach.

Indeks

PrestaShop nie przeszukuje tekstu produktów: szuka we własnym indeksie. Tabela search_word zawiera słowa z katalogu, odrębne dla każdego języka i sklepu, a search_index łączy każdy produkt z każdym z jego słów wraz z wagą. Waga zależy od pola (nazwa, numery referencyjne, opisy, kategoria, marka, tagi, atrybuty, cechy, opcje PS_SEARCH_WEIGHT_*), a waga 0 wyklucza pole z indeksu. Słowa krótsze niż minimalna długość (PS_SEARCH_MINWORDLEN) nie są indeksowane, a „Słowa zabronione” (PS_SEARCH_BLACKLIST) są odrzucane. Indeks aktualizuje się przy zapisie produktu, jeśli włączone jest automatyczne indeksowanie, i odbudowuje się w sekcji Preferencje, Szukaj, za pomocą „Dodaj brakujące produkty do indeksu” i „Przebuduj cały indeks” albo za pomocą adresu URL dla crona pokazanego na tej samej stronie.

Wyszukiwanie

Dla każdego wpisanego słowa Search::find odpytuje indeks warunkiem LIKE na tym słowie. Domyślnie symbol wieloznaczny (wildcard) występuje tylko na końcu („słowo%”). Przy „Szukaj używając części słowa” (PS_SEARCH_START) pojawia się także na początku, a interfejs ostrzega, że może to wymagać dużo zasobów; przy „Wyszukaj dopasowując zakończenia słowa” (PS_SEARCH_END) znika ten na końcu. Zbiory produktów znalezionych dla poszczególnych słów są w PHP przecinane (część wspólna), następnie podzapytanie sumuje wagi każdego produktu na potrzeby trafności, a zapytanie końcowe ładuje wyniki i liczy ich sumę. Przy sortowaniu po cenie cały zbiór jest ładowany i sortowany w PHP, zanim zostanie podzielony na strony.

Wyszukiwanie przybliżone (fuzzy)

Jeśli wyszukiwanie dokładne nic nie znajdzie, a „Wyszukiwanie porównawcze” (PS_SEARCH_FUZZY) jest włączone, PrestaShop odczytuje z indeksu słowa o odpowiedniej długości (przy ponad 100 000 słów tylko te o tej samej długości) i oblicza w PHP odległość Levenshteina od wpisanego słowa, akceptując najbliższe w granicach maksymalnej różnicy (PS_SEARCH_FUZZY_MAX_DIFFERENCE, domyślnie 5 według interfejsu). Liczba prób na wyszukiwanie jest ograniczona przez PS_SEARCH_FUZZY_MAX_LOOP, a interfejs ostrzega, że opcja zużywa zasoby.

Dlaczego zwalnia, gdy katalog rośnie

To mechanizmy, a nie liczby: czasy zależą od katalogu, języków, filtrów i serwera.

  • Symbol wieloznaczny na początku. Według dokumentacji MySQL porównanie LIKE może użyć indeksu jako zakresu tylko wtedy, gdy argument jest stałym ciągiem znaków niezaczynającym się od symbolu wieloznacznego; MariaDB podaje to samo. Indeks search_word (język, sklep, słowo) pomaga przy „słowo%”, a nie przy „%słowo%”.
  • Rozmiar indeksu. search_index ma wiersz dla każdej pary produkt-słowo, przy czym słowa są odrębne dla każdego języka i sklepu: rośnie wraz z liczbą produktów, słów na produkt i języków.
  • Złączenia (join) i sumy wag. Każde wyszukiwanie łączy tabele indeksu z tabelami produktów, a trafność to podzapytanie dla każdego znalezionego produktu.
  • Pętla przybliżona. Po pustym wyszukiwaniu lista słów odczytana z bazy danych jest porównywana po kolei w PHP.
  • Sortowanie po cenie w PHP, które ładuje wszystkie wyniki zamiast dzielić je na strony w zapytaniu.
  • Liczniki filtrów, opisane poniżej.

Filtry: dlaczego licznik może się nie zgadzać

ps_facetedsearch oblicza każdy licznik zapytaniem COUNT(DISTINCT p.id_product) grupowanym według wartości, stosując wybrane filtry z wyjątkiem filtra grupy, która jest właśnie liczona. Liczy produkty, a nie kombinacje. Liczba może odbiegać od wyników z następujących powodów, wszystkich widocznych w kodzie:

  • Cache bloków filtrów. Przy włączonej opcji (jest włączona po instalacji) bloki wraz z ich licznikami są zapisywane w tabeli layered_filter_block dla kategorii, marek i dostawców (nie dla wyszukiwania) i czyszczone przez hooki zapisu produktów, kategorii, atrybutów, cech i reguł cenowych. Wśród zarejestrowanych hooków nie ma żadnego dla zmiany ilości: po aktualizacjach stanów magazynowych poza kartą produktu blok może pozostać stary, dopóki nie użyje się „Wyczyść pamięć podręczną” albo crona czyszczącego.
  • Indeks cen. Filtr ceny używa layered_price_index ze złączeniem wewnętrznym (inner join): produkt nieobecny w indeksie nie pojawia się, gdy filtr jest aktywny. Indeks aktualizuje się przy zapisie produktu oraz z panelu „Indeksy i cache” („Indeksuj brakujące ceny”, „Odbuduj cały indeks cen”); panel zaleca regularne crony, z nocną odbudową.

Co zmienia zewnętrzny silnik

Elasticsearch, OpenSearch i Meilisearch przechowują indeks w osobnej usłudze, zaprojektowanej do przeszukiwania tekstu.

  • Indeks odwrócony. Według dokumentacji Elasticsearch jest to struktura, która kojarzy każdy termin z dokumentami, które go zawierają, z posortowanym słownikiem terminów i, dla każdego z nich, listą dokumentów. Wyszukiwany tekst jest analizowany tak samo jak tekst indeksowany.
  • Trafność. Elasticsearch i OpenSearch używają BM25 jako modelu domyślnego.
  • Literówki. W Elasticsearch parametr fuzziness to odległość edycyjna Levenshteina obliczana przez silnik; wartość AUTO jest zazwyczaj zalecana (od 0 do 2 znaków słowo musi się zgadzać, od 3 do 5 dopuszczalny jest jeden błąd, powyżej 5 dwa). OpenSearch ma ten sam parametr. W Meilisearch tolerancja literówek jest domyślnie włączona: jeden błąd dla terminów o długości co najmniej 5 znaków, dwa od 9 znaków.
  • Języki. Elasticsearch oferuje analizatory dla poszczególnych języków, w tym włoskiego, francuskiego, niemieckiego, angielskiego, hiszpańskiego i niderlandzkiego.
  • Liczniki. Agregacje tworzą podsumowania, takie jak „ile produktów w każdej kategorii”, w tym samym żądaniu wyszukiwania, za pomocą parametru aggs. OpenSearch ostrzega, że zużywają więcej CPU i pamięci niż zapytania.
  • Koszty. To dodatkowa usługa do zainstalowania, aktualizowania i utrzymywania w działaniu, a indeks trzeba utrzymywać zsynchronizowany z katalogiem: każdy produkt istnieje w bazie danych i w silniku. W przypadku małych katalogów natywne wyszukiwanie często wystarcza.

Jak mierzyć przed podjęciem decyzji

  1. Czas strony wyszukiwania. Z terminala: curl -o /dev/null -s -w %{time_starttransfer}\\n https://example.com/index.php\?controller=search\&s=wiertarka. Według dokumentacji curl time_starttransfer to czas w sekundach do pierwszego bajtu, wliczając czas, który serwer poświęca na obliczenie wyniku. Należy wypróbować od 5 do 10 rzeczywistych wyszukiwań, każde trzy razy: kod produktu, słowo z literówką, dwa słowa (ze znakiem plus zamiast spacji), markę.
  2. Log wolnych zapytań. W MySQL i MariaDB jest domyślnie wyłączony, a domyślny próg long_query_time wynosi 10 sekund: na czas testu należy go obniżyć, a następnie użyć EXPLAIN na znalezionych zapytaniach, aby sprawdzić, czy używają indeksu.
  3. Profilowanie PrestaShop. Stała _PS_DEBUG_PROFILING_ w config/defines.inc.php, według komentarza w pliku, pokazuje informacje o wydajności pod każdą stroną. Należy jej używać na kopii testowej.
  4. Statystyki wyszukiwań. Moduł „Wyszukiwarka sklepu” (statssearch) zapisuje przy każdym wyszukiwaniu wyszukiwane słowo, liczbę wyników i datę; w sekcji Statystyki wymienia słowa wyszukiwane więcej niż raz.
  5. Filtr sprawdzony ręcznie. Należy zanotować licznik obok wartości, kliknąć ją i porównać z wyświetlonymi produktami; powtórzyć po zmianie ceny lub stanu magazynowego.
  6. Demo. Należy wypróbować te same wyszukiwania i filtry na demo, które ma duży katalog i aktywny moduł.

Przed zmianą silnika warto też wypróbować ustawienia: wyłączyć „Szukaj używając części słowa”, jeśli nie jest potrzebne, zmniejszyć dopuszczalną liczbę słów przybliżonych, wyzerować wagę pól, które nie są potrzebne, i odbudować indeks.

Jak robi to moduł Wyszukiwarka Elasticsearch i nawigacja fasetowa

  • Silnik do wyboru: wbudowany (czyta bazę danych PrestaShop, żadnej dodatkowej usługi), Elasticsearch, OpenSearch lub Meilisearch.
  • Przy Elasticsearch i OpenSearch wyniki i liczniki filtrów pochodzą z tego samego żądania: agregacje są przesyłane w treści zapytania wyszukiwania.
  • Liczniki działają w trybie automatycznym: są włączone przy silniku zewnętrznym i wyłączone przy silniku wbudowanym, gdzie kosztowałyby jedno zliczanie na grupę filtrów. Można je wymusić na karcie Filtry.
  • Literówki: fuzziness silnika zewnętrznego; przy silniku wbudowanym słownik trigramów, odpytywany dopiero po wyszukiwaniu bez wyników, który wybiera najbliższe słowo za pomocą odległości Levenshteina na ograniczonym zbiorze. Poprawia jedno słowo naraz, nie sortuje według podobieństwa i nie analizuje opisów.
  • Jeśli silnik zewnętrzny nie odpowiada, wyłącznik wyklucza go na 30 sekund, a przy włączonym fallback (jest domyślnie włączony) wyszukiwania wracają do silnika wbudowanego.
  • Indeks podąża za zapisem i usuwaniem produktów oraz zmianami stanów magazynowych; cron chroniony tokenem i asystent reindeksowania odbudowują go.
  • Analiza wyszukiwań z najczęstszymi i tymi bez wyników oraz szablony filtrów dla kategorii.

Zobacz kartę modułu, przeczytaj poradnik instalacji i konfiguracji lub wypróbuj demo.

Źródła

Najczęściej zadawane pytania

Od ilu produktów opłaca się zewnętrzny silnik?

Nie ma progu obowiązującego we wszystkich przypadkach: zależy od produktów, języków, liczby filtrów i serwera. W przypadku małych katalogów natywne wyszukiwanie często wystarcza. Lepiej najpierw zmierzyć, korzystając z powyższych testów.

Czy wyszukiwanie przybliżone w PrestaShop spowalnia każde wyszukiwanie?

Nie, włącza się tylko wtedy, gdy wyszukiwanie dokładne nic nie znajduje: wtedy odczytuje słowa kandydujące z bazy danych i oblicza w PHP odległość Levenshteina. Koszt obciąża wyszukiwania bez wyników.

Dlaczego liczba obok filtra nie zgadza się z wyświetlonymi produktami?

Przyczyny widoczne w kodzie to cache bloków filtrów, nieczyszczona przez niektóre zmiany stanów magazynowych, oraz nieaktualny indeks cen lub atrybutów. Grupa, która jest już filtrowana, jest ponadto liczona bez własnego filtra.

Czy silnik zewnętrzny jest zawsze szybszy?

Niekoniecznie. Przenosi wyszukiwanie na indeks zaprojektowany do tekstu, ale jest to dodatkowa usługa, którą trzeba utrzymywać w działaniu i synchronizować, a agregacje zużywają więcej CPU i pamięci niż zapytania.

Czy sam moduł wystarczy?

Nie. Przy silniku wbudowanym wyszukiwanie pozostaje wyszukiwaniem w bazie danych PrestaShop, z lepszymi filtrami i korekcją literówek, ale bez zmiany podstawowego mechanizmu. Silnik zewnętrzny trzeba zainstalować, aktualizować i utrzymywać w działaniu, a synonimy i analizatory trzeba skonfigurować. Najpierw warto zmierzyć.

Dodaj komentarz

Komentarze są moderowane przed publikacją.

← Blog

Ładowanie...
Powrót do góry