Trage zoekfunctie in PrestaShop: oorzaken, filters, meten

door Presta365 Technische handleidingen

De module voor dit probleem

Elasticsearch-zoekfunctie & gefacetteerde navigatie

Zoeken met de ingebouwde zoekmachine of met Elasticsearch, OpenSearch en Meilisearch, tolerantie voor typefouten, gefacetteerde filters en analyse van zoekopdrachten zonder resultaten. De module wordt geïnstalleerd met de ingebouwde zoekmachine en een externe zoekmachine wordt gekoppeld wanneer dat nodig is. PrestaShop 1.7.7, 8 en 9, 12 maanden updates inbegrepen, daarna is verlengen optioneel.

Module bekijkenLees de handleidingProbeer de demo

Hoe de native zoekfunctie van PrestaShop zoekt

Geverifieerd in de code van PrestaShop 9.1.5 (classes/Search.php) en van de module ps_facetedsearch 5.0.0; de bestanden staan in de bronnen.

De index

PrestaShop doorzoekt niet de tekst van de producten: het zoekt in een eigen index. De tabel search_word bevat de woorden van de catalogus, afzonderlijk per taal en per webwinkel, en search_index koppelt elk product aan elk van zijn woorden met een gewicht. Het gewicht hangt af van het veld (naam, referenties, beschrijvingen, categorie, merk, tags, attributen, kenmerken, opties PS_SEARCH_WEIGHT_*) en een gewicht van 0 sluit het veld uit van de index. Woorden onder de minimale lengte (PS_SEARCH_MINWORDLEN) worden niet geïndexeerd en de “Zwartelijst woorden” (PS_SEARCH_BLACKLIST) worden weggelaten. De index wordt bijgewerkt wanneer een product wordt opgeslagen als automatisch indexeren actief is en wordt opnieuw opgebouwd via Winkelinstellingen, Zoeken, met “Ontbrekende producten toevoegen aan de index” en “Vernieuwd de gehele index”, of met de URL voor de cron die op dezelfde pagina wordt getoond.

Het zoeken

Voor elk ingevoerd woord bevraagt Search::find de index met een LIKE-voorwaarde op het woord. Standaard staat het jokerteken alleen aan het einde (“woord%”). Met “Zoek in het woord” (PS_SEARCH_START) verschijnt het jokerteken ook aan het begin, en de interface waarschuwt dat dit veel resources kan vragen; met “Zoeken op exacte einde” (PS_SEARCH_END) verdwijnt dat aan het einde. De producten die voor de afzonderlijke woorden zijn gevonden, worden in PHP gekruist (doorsnede), daarna telt een subquery de gewichten van elk product op voor de relevantie en laadt een eindquery de resultaten en telt het totaal. Bij sortering op prijs wordt de hele set in PHP geladen en gesorteerd voordat ze wordt opgedeeld in pagina’s.

Benaderend zoeken

Als het exacte zoeken niets vindt en “Fuzzy zoeken” (PS_SEARCH_FUZZY) actief is, leest PrestaShop uit de index de woorden van passende lengte (bij meer dan 100.000 woorden alleen die van dezelfde lengte) en berekent in PHP de Levenshtein-afstand tot het ingevoerde woord, waarbij het dichtstbijzijnde wordt geaccepteerd binnen een maximaal verschil (PS_SEARCH_FUZZY_MAX_DIFFERENCE, standaard 5 volgens de interface). Het aantal pogingen per zoekopdracht wordt beperkt door PS_SEARCH_FUZZY_MAX_LOOP, en de interface waarschuwt dat de optie resources verbruikt.

Waarom het langzamer wordt naarmate de catalogus groeit

Het zijn mechanismen, geen getallen: de tijden hangen af van catalogus, talen, filters en server.

  • Het jokerteken aan het begin. Volgens de MySQL-documentatie kan een LIKE-vergelijking een index alleen als bereik gebruiken als het argument een constante string is die niet met een jokerteken begint; MariaDB zegt hetzelfde. De index van search_word (taal, webwinkel, woord) helpt bij “woord%”, niet bij “%woord%”.
  • De grootte van de index. search_index heeft een rij voor elk paar product-woord, met woorden die per taal en per webwinkel verschillen: de index groeit met producten, woorden per product en talen.
  • Joins en sommen van gewichten. Elke zoekopdracht koppelt de tabellen van de index aan die van de producten en de relevantie is een subquery voor elk gevonden product.
  • De benaderende lus. Na een lege zoekopdracht wordt een uit de database gelezen lijst woorden in PHP één voor één vergeleken.
  • Sortering op prijs in PHP, die alle resultaten laadt in plaats van ze in de query in pagina’s te verdelen.
  • De tellingen van de filters, hieronder beschreven.

Filters: waarom een telling niet klopt

ps_facetedsearch berekent elke telling met een query COUNT(DISTINCT p.id_product) gegroepeerd op waarde, waarbij de geselecteerde filters worden toegepast behalve die van de groep die wordt geteld. Het telt producten, geen combinaties. Een getal kan om deze redenen afwijken van de resultaten, allemaal zichtbaar in de code:

  • Cache van de filterblokken. Met de optie actief (dat is zo na de installatie) worden de blokken met hun tellingen opgeslagen in de tabel layered_filter_block voor categorieën, merken en leveranciers (niet voor de zoekfunctie) en geleegd door de opslaghooks van producten, categorieën, attributen, kenmerken en prijsregels. Onder de geregistreerde hooks zit er geen voor een wijziging van de hoeveelheid: na voorraadwijzigingen buiten de productpagina kan het blok oud blijven totdat “Cache legen” of de cron voor het legen wordt gebruikt.
  • Prijsindex. Het prijsfilter gebruikt layered_price_index met een inner join: een product dat niet in de index staat, verschijnt niet wanneer het filter actief is. De index wordt bijgewerkt bij het opslaan van het product en via het paneel “Indexen en caches” (“Indexeer alle ontbrekende prijzen”, “Herbouw de gehele prijs index”); het paneel adviseert regelmatige crons, met een nachtelijke herbouw.

Wat verandert er met een externe zoekmachine

Elasticsearch, OpenSearch en Meilisearch houden de index in een afzonderlijke dienst, ontworpen om tekst te doorzoeken.

  • Omgekeerde index. Volgens de documentatie van Elasticsearch is dit een structuur die elke term koppelt aan de documenten die hem bevatten, met een gesorteerd woordenboek van de termen en, voor elke term, een lijst van documenten. De gezochte tekst wordt op dezelfde manier geanalyseerd als de geïndexeerde tekst.
  • Relevantie. Elasticsearch en OpenSearch gebruiken BM25 als standaardmodel.
  • Typefouten. In Elasticsearch is de parameter fuzziness een bewerkingsafstand van Levenshtein die door de zoekmachine wordt berekend; de waarde AUTO wordt over het algemeen aanbevolen (bij 0 tot 2 tekens moet het woord overeenkomen, bij 3 tot 5 is één fout toegestaan, boven 5 twee). OpenSearch heeft dezelfde parameter. In Meilisearch is de tolerantie voor typefouten standaard actief: één fout voor termen van minstens 5 tekens, twee vanaf 9.
  • Talen. Elasticsearch biedt analyzers per taal, waaronder Italiaans, Frans, Duits, Engels, Spaans en Nederlands.
  • Tellingen. Aggregaties leveren samenvattingen zoals “hoeveel producten in elke categorie” in hetzelfde zoekverzoek, met de parameter aggs. OpenSearch waarschuwt dat ze meer CPU en geheugen verbruiken dan queries.
  • Kosten. Het is een extra dienst die moet worden geïnstalleerd, bijgewerkt en draaiend gehouden, en de index moet worden gesynchroniseerd met de catalogus: elk product bestaat in de database en in de zoekmachine. Voor kleine catalogi volstaat de native zoekfunctie vaak.

Hoe u meet voordat u beslist

  1. Laadtijd van de zoekpagina. Vanuit een terminal: curl -o /dev/null -s -w %{time_starttransfer}\\n https://example.com/index.php\?controller=search\&s=boormachine. Volgens de documentatie van curl is time_starttransfer de tijd in seconden tot de eerste byte, inclusief de tijd die de server nodig heeft om het resultaat te berekenen. Probeer 5 tot 10 echte zoekopdrachten, elk drie keer: een productcode, een woord met een typefout, twee woorden (met het plusteken in plaats van de spatie), een merk.
  2. Log van trage queries. In MySQL en MariaDB staat deze standaard uit en de standaardlimiet van long_query_time is 10 seconden: verlaag die voor de test en gebruik daarna EXPLAIN op de gevonden queries om te zien of ze een index gebruiken.
  3. Profiel van PrestaShop. De constante _PS_DEBUG_PROFILING_ in config/defines.inc.php toont volgens de opmerking in het bestand prestatie-informatie onder elke pagina. Gebruik die op een testkopie.
  4. Statistieken van de zoekopdrachten. De module “Zoekopdrachten” (statssearch) slaat bij elke zoekopdracht het gezochte woord, het aantal resultaten en de datum op; in Statistieken somt die de woorden op die vaker dan één keer zijn gezocht.
  5. Een filter met de hand. Noteer de telling naast een waarde, klik erop en vergelijk met de getoonde producten; herhaal na het wijzigen van een prijs of een voorraad.
  6. De demo. Probeer dezelfde zoekopdrachten en dezelfde filters op de demo, die een grote catalogus heeft en de actieve module.

Voordat u van zoekmachine wisselt, loont het ook om de instellingen te proberen: “Zoek in het woord” uitzetten als het niet nodig is, de toegestane benaderende woorden verminderen, het gewicht van de velden die u niet nodig hebt op nul zetten en de index opnieuw opbouwen.

Hoe de module Elasticsearch-zoekfunctie & gefacetteerde navigatie het doet

  • Zoekmachine naar keuze: ingebouwd (leest de database van PrestaShop, geen extra dienst), Elasticsearch, OpenSearch of Meilisearch.
  • Met Elasticsearch en OpenSearch komen resultaten en filtertellingen uit hetzelfde verzoek: de aggregaties reizen mee in de body van de zoekopdracht.
  • De tellingen staan in automatische modus: actief met een externe zoekmachine, uit bij de ingebouwde zoekmachine, waar ze één telling per filtergroep zouden kosten. Via het tabblad Facetten kunnen ze worden geforceerd.
  • Typefouten: fuzziness van de externe zoekmachine; bij de ingebouwde zoekmachine een woordenboek van trigrammen, dat alleen na een zoekopdracht zonder resultaten wordt geraadpleegd en het dichtstbijzijnde woord kiest met de Levenshtein-afstand op een beperkte verzameling. Het corrigeert één woord tegelijk, sorteert niet op overeenkomst en kijkt niet naar de beschrijvingen.
  • Als de externe zoekmachine niet antwoordt, sluit een schakelaar hem 30 seconden uit en, met de fallback actief (dat is standaard zo), vallen de zoekopdrachten terug op de ingebouwde zoekmachine.
  • De index volgt het opslaan en verwijderen van producten en de voorraadwijzigingen; een cron beveiligd met een token en een assistent voor herindexering bouwen hem opnieuw op.
  • Analyse van zoekopdrachten met de meest voorkomende en die zonder resultaten, en filtersjablonen per categorie.

Bekijk de productpagina van de module, lees de handleiding voor installatie en configuratie of probeer de demo.

Bronnen

Veelgestelde vragen

Vanaf hoeveel producten is een externe zoekmachine de moeite waard?

Er bestaat geen drempel die voor iedereen geldt: het hangt af van producten, talen, aantal filters en server. Voor kleine catalogi volstaat de native zoekfunctie vaak. Beter eerst meten, met de bovenstaande tests.

Vertraagt het benaderende zoeken van PrestaShop elke zoekopdracht?

Nee, het treedt alleen op wanneer het exacte zoeken niets vindt: dan leest het de kandidaatwoorden uit de database en berekent in PHP de Levenshtein-afstand. De kosten wegen op de zoekopdrachten zonder resultaten.

Waarom komt het getal naast een filter niet overeen met de getoonde producten?

De oorzaken die in de code zichtbaar zijn, zijn de cache van de filterblokken, die door sommige voorraadwijzigingen niet wordt geleegd, en een niet bijgewerkte prijs- of attribuutindex. De groep die al is gefilterd, wordt bovendien geteld zonder haar eigen filter.

Is een externe zoekmachine altijd sneller?

Niet per se. Het verplaatst het zoeken naar een index die voor tekst is ontworpen, maar het is een extra dienst die draaiend en gesynchroniseerd moet worden gehouden, en aggregaties verbruiken meer CPU en geheugen dan queries.

Volstaat de module op zichzelf?

Nee. Met de ingebouwde zoekmachine blijft het zoeken een zoekopdracht op de database van PrestaShop, met betere filters en correctie van typefouten maar zonder het onderliggende mechanisme te veranderen. Een externe zoekmachine moet worden geïnstalleerd, bijgewerkt en draaiend gehouden, en synoniemen en analyzers moeten worden geconfigureerd. Eerst meten loont.

Laat een reactie achter

Reacties worden gemodereerd voordat ze worden gepubliceerd.

← Blog

Laden ...
Terug naar boven