Klient, który wpisuje frazę w wyszukiwarkę sklepu, zwykle wie, czego chce, i jest o krok od zakupu – pod warunkiem, że coś znajdzie. W tym artykule, otwierającym serię o AI w e-commerce, zaczynamy od podstaw: przeglądamy klasyczne sposoby wyszukiwania, od LIKE w SQL, przez full-text w MySQL i PostgreSQL, własne tabele indeksu i Sphinksa, aż po Elasticsearch, Meilisearch i usługi SaaS. Podpowiadamy też, co wybrać do jakiego sklepu.
Wyszukiwarka w sklepie internetowym – od LIKE do Elasticsearch
22.10.2026 | Autor: Marcin Wiercioch
Czego klient oczekuje od wyszukiwarki
Wyszukiwarka w sklepie to coś więcej niż pole tekstowe. Klient wpisuje frazę tak, jak myśli i mówi, a nie tak, jak produkt został nazwany w bazie. Dobra wyszukiwarka musi poradzić sobie z kilkoma rzeczami naraz:
- Literówki i brak polskich znaków – „adidsa”, „sluchawki bezprzewodowe”.
- Odmiana – „kurtka”, „kurtki”, „kurtek”, „kurtkę”; „buty damskie” i „damskich butów”.
- Synonimy – „laptop” i „notebook”, „bluza z kapturem” i „hoodie”.
- Kody – SKU, EAN, symbol producenta, wpisywane z myślnikiem, bez niego albo ze spacją („XR-200”, „xr200”, „XR 200”).
- Trafność – produkt z frazą w nazwie powinien być wyżej niż ten, który wspomina o niej w trzecim akapicie opisu, a dostępny wyżej niż wyprzedany.
- Podpowiedzi w trakcie pisania – w ułamku sekundy, przy każdym naciśnięciu klawisza.
- Filtry – po wpisaniu „kurtka” klient chce zawęzić wyniki po rozmiarze, kolorze i cenie, najlepiej z liczbą produktów przy każdej opcji.
Język polski stawia poprzeczkę wyjątkowo wysoko. Siedem przypadków i polskie znaki sprawiają, że rozwiązania projektowane z myślą o angielskim, gdzie zwykle wystarczy odciąć końcówkę „-s”, u nas działają przeciętnie. Przez ten pryzmat przyjrzymy się każdemu z poniższych podejść.
Najprostsze podejście: LIKE '%fraza%’
Tak domyślnie szuka WordPress, a więc i WooCommerce: każde słowo frazy jest wyszukiwane operatorem LIKE w tytule, zajawce i treści wpisu. W uproszczeniu zapytanie wygląda tak:
SELECT p.ID, p.post_title
FROM wp_posts p
WHERE p.post_type = 'product'
AND p.post_status = 'publish'
AND (p.post_title LIKE '%kurtka%' OR p.post_excerpt LIKE '%kurtka%' OR p.post_content LIKE '%kurtka%')
AND (p.post_title LIKE '%zimowa%' OR p.post_excerpt LIKE '%zimowa%' OR p.post_content LIKE '%zimowa%')
ORDER BY p.post_title LIKE '%kurtka zimowa%' DESC, p.post_date DESC;
Zaleta jest jedna, ale istotna: zero konfiguracji. Wady łatwo przewidzieć:
- Brak indeksu. LIKE ze znakiem % na początku nie skorzysta ze zwykłego indeksu, więc baza przy każdym wyszukiwaniu skanuje wszystkie produkty. Przy kilkuset pozycjach nikt tego nie zauważy, przy kilkudziesięciu tysiącach z długimi opisami już tak.
- Zero rozumienia języka. Fraza „kurtki zimowe” nie znajdzie produktu „Kurtka zimowa męska”, bo żadne z tych słów nie zawiera się w drugim.
- Fałszywe trafienia. „kot” znajdzie także „kotwicę” i „szkotkę”.
- Prymitywna trafność. WordPress układa wyniki według kilku prostych reguł (cała fraza w tytule, wszystkie słowa w tytule, którekolwiek słowo w tytule, fraza w zajawce, fraza w treści). Nie ma wag dla kategorii, atrybutów czy popularności.
- Kody produktów. Domyślna wyszukiwarka WooCommerce na froncie sklepu nie przeszukuje SKU ani atrybutów. Klient, który przepisuje kod z faktury czy katalogu, dostaje zero wyników.
LIKE ma jedno uczciwe zastosowanie: wyszukiwanie po początku tekstu (LIKE 'XR-2%’) na zindeksowanej kolumnie, np. z kodem produktu. Tu indeks zadziała i zapytanie będzie szybkie.
FULLTEXT w MySQL i MariaDB
Od MySQL 5.6 indeksy pełnotekstowe działają w silniku InnoDB. Baza buduje indeks odwrócony (słowo → lista rekordów, w których występuje), a zapytanie MATCH … AGAINST zwraca wyniki razem z oceną trafności.
ALTER TABLE products ADD FULLTEXT INDEX ft_products (name, description);
-- tryb naturalny: wyniki z oceną trafności
SELECT id, name, MATCH(name, description) AGAINST('kurtka zimowa') AS score
FROM products
WHERE MATCH(name, description) AGAINST('kurtka zimowa')
ORDER BY score DESC
LIMIT 20;
-- tryb boolean: słowa wymagane, wykluczone i wyszukiwanie po prefiksie
SELECT id, name
FROM products
WHERE MATCH(name, description) AGAINST('+kurtk* +zimow* -dziecięca' IN BOOLEAN MODE);
To ogromny skok wydajności względem LIKE i rozwiązanie dostępne „za darmo” w bazie, którą sklep i tak ma. Ograniczenia są jednak wyraźne:
- Brak obsługi polskiej odmiany. MySQL nie potrafi sprowadzić różnych form polskiego słowa do jednej, podstawowej. Częściowo ratuje tryb boolean z gwiazdką („kurtk*” znajdzie „kurtka”, „kurtki” i „kurtkę”), ale słowa, które w odmianie zmieniają brzmienie („pies” i „psa”), pozostają poza zasięgiem.
- Minimalna długość słowa. InnoDB domyślnie indeksuje słowa od trzech znaków (innodb_ft_min_token_size), więc „TV” czy „4K” wypadają z indeksu. Zmiana wymaga konfiguracji serwera, co na hostingu współdzielonym zwykle nie wchodzi w grę.
- Słowa pomijane. Wbudowana lista słów, które baza ignoruje (np. „the”, „and”), jest angielska.
- Brak tolerancji literówek i synonimów.
Dla sklepu z kilkoma tysiącami produktów to często wystarczające i rozsądne rozwiązanie, zwłaszcza w połączeniu z własną tabelą indeksu, o której za chwilę.
PostgreSQL: full-text i tolerancja literówek
PostgreSQL ma znacznie bogatszy wbudowany mechanizm pełnotekstowy: typy tsvector i tsquery, słowniki językowe, wagi dla poszczególnych pól (od A do D) i ranking ts_rank. Polskiego słownika nie ma w standardowej instalacji, ale można podpiąć słownik w formacie ispell (np. oparty o słowniki Hunspell z projektu sjp.pl). Wtedy „kurtek” i „kurtka” sprowadzają się do tej samej formy podstawowej. Rozszerzenie pg_trgm dokłada tolerancję literówek (porównuje słowa po krótkich, trzyliterowych fragmentach), a unaccent pozwala ignorować polskie znaki.
W przykładzie używamy konfiguracji simple, która nie rozpoznaje odmiany. Po zainstalowaniu polskiego słownika wystarczy podmienić ją na własną konfigurację.
CREATE EXTENSION IF NOT EXISTS pg_trgm;
ALTER TABLE products ADD COLUMN search_vector tsvector
GENERATED ALWAYS AS (
setweight(to_tsvector('simple', coalesce(name, '')), 'A') ||
setweight(to_tsvector('simple', coalesce(description, '')), 'B')
) STORED;
CREATE INDEX idx_products_search ON products USING GIN (search_vector);
CREATE INDEX idx_products_name_trgm ON products USING GIN (name gin_trgm_ops);
-- wyszukiwanie pełnotekstowe z rankingiem
SELECT id, name, ts_rank(search_vector, query) AS score
FROM products, websearch_to_tsquery('simple', 'kurtka zimowa') AS query
WHERE search_vector @@ query
ORDER BY score DESC
LIMIT 20;
-- tolerancja literówek: "kurtak zimowa" nadal znajdzie produkt
SELECT id, name, similarity(name, 'kurtak zimowa') AS score
FROM products
WHERE name % 'kurtak zimowa'
ORDER BY score DESC
LIMIT 20;
Jeśli sklep działa na PostgreSQL (jak wiele instalacji Syliusa, Saleor czy Medusa), to często najlepszy pierwszy krok, zanim sięgnie się po osobny silnik wyszukiwania.
Własna tabela z zaindeksowanymi danymi
Zamiast przeszukiwać tabele produktów na żywo, można przygotować dane z wyprzedzeniem. Przy każdym zapisie produktu budujemy jeden rekord ze wszystkimi danymi potrzebnymi do wyszukiwania: nazwa, SKU w kilku wariantach zapisu, kategorie, wartości atrybutów, wszystko znormalizowane (małe litery, bez polskich znaków, bez myślników). Wyszukiwanie odbywa się potem w jednej, wąskiej tabeli z indeksami FULLTEXT zamiast przez JOIN-y po pół bazy.
Tak działają popularne wtyczki do WordPressa: Relevanssi i SearchWP budują własne tabele indeksu. PrestaShop od lat trzyma słowa w tabelach ps_search_word i ps_search_index, z wagami ustawianymi w panelu (nazwa, indeks, opisy, kategoria, producent, atrybuty, cechy). Prosta wersja dla WooCommerce może wyglądać tak:
CREATE TABLE wp_product_search_index (
product_id BIGINT UNSIGNED NOT NULL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
codes VARCHAR(255) NOT NULL,
keywords TEXT NOT NULL,
in_stock TINYINT(1) NOT NULL DEFAULT 0,
FULLTEXT KEY ft_all (title, codes, keywords),
FULLTEXT KEY ft_title (title),
FULLTEXT KEY ft_codes (codes),
FULLTEXT KEY ft_keywords (keywords)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
<?php
// Normalizacja: małe litery, bez polskich znaków i znaków specjalnych
function normalize_search_text(string $text): string
{
$text = mb_strtolower(wp_strip_all_tags($text));
$text = strtr($text, [
'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n',
'ó' => 'o', 'ś' => 's', 'ź' => 'z', 'ż' => 'z',
]);
$text = preg_replace('/[^a-z0-9]+/', ' ', $text);
return trim(preg_replace('/\s+/', ' ', $text));
}
// Przy każdym zapisie produktu odświeżamy jego rekord w indeksie
add_action('woocommerce_new_product', 'update_product_search_index');
add_action('woocommerce_update_product', 'update_product_search_index');
function update_product_search_index(int $product_id): void
{
global $wpdb;
$product = wc_get_product($product_id);
if (!$product) {
return;
}
$sku = (string) $product->get_sku();
// "XR-200" zapisujemy jako "xr 200" i "xr200", żeby każdy wariant dawał trafienie
$codes = normalize_search_text($sku) . ' ' . strtolower(preg_replace('/[^a-z0-9]/i', '', $sku));
$terms = wp_get_post_terms($product_id, ['product_cat', 'product_tag'], ['fields' => 'names']);
$attribute_values = [];
foreach ($product->get_attributes() as $attribute) {
$attribute_values = array_merge($attribute_values, $attribute->is_taxonomy()
? wc_get_product_terms($product_id, $attribute->get_name(), ['fields' => 'names'])
: $attribute->get_options());
}
$wpdb->replace($wpdb->prefix . 'product_search_index', [
'product_id' => $product_id,
'title' => normalize_search_text($product->get_name()),
'codes' => $codes,
'keywords' => normalize_search_text(implode(' ', array_merge(
is_array($terms) ? $terms : [],
$attribute_values,
[$product->get_short_description()]
))),
'in_stock' => $product->is_in_stock() ? 1 : 0,
]);
}
Frazę od klienta przepuszczamy przez tę samą funkcję normalizującą. Prosty trik: dłuższe słowa skracamy o jedną lub dwie litery i dodajemy gwiazdkę, co jest bardzo prostym sposobem na obsługę odmiany („kurtka zimowa” → „kurtk* zimow*”). Trafienie w kod liczy się bardziej niż w nazwie, a nazwa bardziej niż słowa kluczowe, a produkty dostępne lądują wyżej:
SELECT product_id,
MATCH(codes) AGAINST('kurtk* zimow*' IN BOOLEAN MODE) * 5
+ MATCH(title) AGAINST('kurtk* zimow*' IN BOOLEAN MODE) * 3
+ MATCH(keywords) AGAINST('kurtk* zimow*' IN BOOLEAN MODE)
+ in_stock * 2 AS score
FROM wp_product_search_index
WHERE MATCH(title, codes, keywords) AGAINST('kurtk* zimow*' IN BOOLEAN MODE)
ORDER BY score DESC
LIMIT 20;
Zalety: pełna kontrola, brak dodatkowej infrastruktury i kody produktów działające dokładnie tak, jak chcemy. Wady: trzeba pilnować aktualności indeksu (importy CSV, masowe zmiany stanów czy synchronizacja z ERP potrafią ominąć automatyczną aktualizację indeksu, więc przyda się też pełna przebudowa uruchamiana z crona), a literówek i synonimów nadal brak, chyba że dopiszemy je sami. Słownik synonimów to zwykle osobna tabela i rozwinięcie frazy przed wykonaniem zapytania.
Indeks w plikach binarnych: Lucene, Zend_Search_Lucene i Sphinx
U podstaw niemal każdej poważnej wyszukiwarki leży ta sama idea: indeks odwrócony. Zamiast trzymać listę produktów i szukać w nich słów, trzyma się listę słów, a przy każdym z nich listę produktów, w których występuje, razem z pozycjami i częstotliwością. Wyszukanie frazy to wtedy kilka odczytów i przecięcie list, a nie skanowanie całego katalogu.
Apache Lucene, biblioteka Javy rozwijana od końca lat 90., zapisuje taki indeks w segmentach: niezmiennych plikach binarnych na dysku, które w tle są scalane w większe. W świecie PHP popularny był kiedyś Zend_Search_Lucene z Zend Framework 1, czyli implementacja Lucene napisana w czystym PHP, trzymająca indeks w plikach w katalogu aplikacji, bez żadnego dodatkowego serwera. Wygodne na start, ale przy większych katalogach wolne, pamięciożerne i podatne na problemy z blokadami przy równoczesnych zapisach. Dziś to już rozwiązanie historyczne.
Drugim weteranem jest Sphinx: osobny serwer (searchd), który pobiera dane prosto zapytaniem SQL (narzędzie indexer) i trzyma indeks we własnych plikach binarnych. Był bardzo szybki i mówił protokołem MySQL (SphinxQL), więc z aplikacji odpytywało się go jak zwykłą bazę danych. Przez lata napędzał wyszukiwarki wielu polskich sklepów i serwisów. Gdy rozwój Sphinksa zwolnił, a kolejne wydania przestały być publikowane jako open source, w 2017 roku powstał fork Manticore Search. Jest aktywnie rozwijany do dziś, m.in. o indeksy aktualizowane w czasie rzeczywistym i wyszukiwanie wektorowe.
-- Manticore Search: tabela real-time, obsługiwana zwykłym klientem MySQL
CREATE TABLE products (title text, sku string, price float, in_stock bool) min_prefix_len='3';
INSERT INTO products (id, title, sku, price, in_stock)
VALUES (1, 'Kurtka zimowa męska', 'XR-200', 399.0, 1);
SELECT id, title, WEIGHT() AS score
FROM products
WHERE MATCH('kurtk*') AND in_stock = 1
ORDER BY score DESC
LIMIT 20;
Elasticsearch i OpenSearch, czyli ciężka artyleria
Elasticsearch to rozproszony serwer wyszukiwania zbudowany na Lucene. Komunikuje się przez REST API i JSON, a w zamian oferuje wszystko, czego brakowało wcześniej: analizatory językowe, tolerancję literówek (fuzziness), synonimy, autouzupełnianie, agregacje do filtrów z licznikami i skalowanie na wiele węzłów. Dla polskiego jest oficjalna wtyczka analysis-stempel, a do dokładniejszej analizy, opartej na słowniku języka polskiego, służy Morfologik.
Analizator to przepis na przetworzenie tekstu: podział na słowa, zamiana na małe litery, sprowadzenie słowa do formy podstawowej i usunięcie polskich znaków. Ten sam przepis stosowany jest do frazy wpisanej przez klienta, więc „kurtek zimowych” i „Kurtka zimowa” spotykają się w indeksie w tej samej postaci. Indeks z taką konfiguracją tworzymy żądaniem PUT /products:
{
"settings": {
"analysis": {
"analyzer": {
"polish_products": {
"tokenizer": "standard",
"filter": ["lowercase", "polish_stem", "asciifolding"]
}
}
}
},
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "polish_products" },
"description": { "type": "text", "analyzer": "polish_products" },
"sku": { "type": "keyword" },
"category": { "type": "keyword" },
"price": { "type": "scaled_float", "scaling_factor": 100 },
"in_stock": { "type": "boolean" }
}
}
}
Zapytanie (POST /products/_search) łączy wyszukiwanie z tolerancją literówek, filtrowanie i agregacje, z których budujemy filtry z licznikami w bocznej kolumnie:
{
"query": {
"bool": {
"must": {
"multi_match": {
"query": "kurtek zimowych",
"fields": ["name^3", "description"],
"fuzziness": "AUTO"
}
},
"filter": [{ "term": { "in_stock": true } }]
}
},
"aggs": {
"categories": { "terms": { "field": "category" } },
"price_ranges": {
"range": {
"field": "price",
"ranges": [{ "to": 100 }, { "from": 100, "to": 300 }, { "from": 300 }]
}
}
}
}
Ceną za te możliwości jest infrastruktura. Elasticsearch działa na JVM i potrzebuje sporo pamięci RAM, więc w praktyce to osobny serwer albo usługa zarządzana, do tego synchronizacja danych ze sklepu (kolejka, reindeksacja, obsługa błędów). Przy dużych katalogach to rynkowy standard: Magento od wersji 2.4 wręcz wymaga Elasticsearch lub OpenSearch, a WooCommerce może z niego korzystać m.in. przez wtyczkę ElasticPress.
Słowo o licencjach: w 2021 roku Elastic zmienił licencję z Apache 2.0 na SSPL i Elastic License. W odpowiedzi AWS stworzył fork OpenSearch (Apache 2.0, dziś rozwijany pod skrzydłami Linux Foundation), a w 2024 roku Elastic ponownie dodał opcję open source w postaci licencji AGPL. Na poziomie podstawowych zapytań oba projekty są dla sklepu wymienne, choć z każdą wersją coraz bardziej różnią się w szczegółach.
Nowa fala: Meilisearch i Typesense
Pomiędzy MySQL a Elasticsearchem jest miejsce na lżejsze silniki, projektowane od początku z myślą o wyszukiwaniu „jak w aplikacji”: wyniki w trakcie pisania, literówki obsługiwane bez konfiguracji i sensowna trafność od pierwszego uruchomienia.
- Meilisearch (Rust, open source). Instalacja to jeden plik binarny lub kontener, a indeksowanie to wysłanie JSON-a z produktami. Tolerancja literówek, filtry z licznikami wyników, sortowanie i synonimy są w standardzie.
- Typesense (C++, open source). Podobna filozofia, indeks trzymany w pamięci RAM, bardzo niskie opóźnienia i wbudowana obsługa klastra.
Oba współpracują z biblioteką InstantSearch, z której szybko złożymy frontend wyszukiwarki z podpowiedziami i filtrami. Haczyk dla polskiego: żaden z nich nie radzi sobie dobrze z polską odmianą. Odmianę częściowo maskuje wyszukiwanie po prefiksach i tolerancja literówek, ale „psa” nadal nie znajdzie „pies”. Warto przetestować to na własnym katalogu przed podjęciem decyzji. Tak wygląda start z Meilisearch:
# Meilisearch lokalnie w kontenerze
docker run -d -p 7700:7700 -e MEILI_MASTER_KEY='change-me-master-key' getmeili/meilisearch:latest
# Ustawienia indeksu: po czym szukamy i po czym filtrujemy
curl -X PATCH 'http://localhost:7700/indexes/products/settings' \
-H 'Authorization: Bearer change-me-master-key' \
-H 'Content-Type: application/json' \
--data-binary '{ "searchableAttributes": ["name", "sku", "category", "description"], "filterableAttributes": ["category", "in_stock"] }'
# Wrzucenie produktów do indeksu
curl -X POST 'http://localhost:7700/indexes/products/documents' \
-H 'Authorization: Bearer change-me-master-key' \
-H 'Content-Type: application/json' \
--data-binary @products.json
# Wyszukiwanie z literówką i filtrem
curl -X POST 'http://localhost:7700/indexes/products/search' \
-H 'Authorization: Bearer change-me-master-key' \
-H 'Content-Type: application/json' \
--data-binary '{ "q": "kurtak zimowa", "filter": "in_stock = true" }'
Wyszukiwarka jako usługa: Algolia, Doofinder, Luigi’s Box
Ostatnia opcja to w ogóle nie utrzymywać silnika samodzielnie. Usługi SaaS przejmują indeks, infrastrukturę, a często także cały frontend wyszukiwarki (okno z podpowiedziami, filtry, stronę wyników). Do sklepu wpina się je wtyczką albo feedem produktowym.
- Algolia: najbardziej znana, bardzo szybka, z rozbudowanym API dla programistów. Płaci się za liczbę rekordów i zapytań.
- Doofinder: nastawiony na e-commerce, z gotowymi integracjami m.in. z WooCommerce, PrestaShop i Shopify; wdrożenie bez programowania.
- Luigi’s Box: słowacki dostawca popularny w Europie Środkowej, mocny w analityce wyszukiwań i rekomendacjach.
Plusy: szybkie wdrożenie, analityka (czego klienci szukają i czego nie znajdują, co jest bezcenne dla działu zakupów) oraz ręczne przypinanie wybranych produktów do konkretnych fraz. Minusy: abonament rosnący razem z ruchem i katalogiem, zależność od dostawcy i dane produktowe poza własną infrastrukturą.
Porównanie
| Rozwiązanie | Polska odmiana | Literówki | Filtry | Infrastruktura | Dla kogo |
|---|---|---|---|---|---|
| LIKE | nie | nie | nie | brak | do kilkuset produktów |
| MySQL FULLTEXT | częściowo (prefiksy) | nie | ręcznie w SQL | brak | małe i średnie sklepy |
| PostgreSQL full-text + pg_trgm | tak (słownik ispell) | tak | ręcznie w SQL | brak | sklepy na PostgreSQL |
| Własna tabela indeksu | częściowo | ręcznie | ręcznie | brak | gdy liczą się kody i pełna kontrola |
| Manticore / Sphinx | częściowo | częściowo | tak | własny serwer | duże katalogi przy małym budżecie |
| Elasticsearch / OpenSearch | tak (Stempel, Morfologik) | tak | tak | klaster lub usługa zarządzana | duże sklepy, złożone filtry |
| Meilisearch / Typesense | słabo | tak | tak | lekki serwer | szybkie wdrożenie, średnie katalogi |
| SaaS | zależnie od usługi | tak | tak | brak (abonament) | sklepy bez własnego zespołu IT |
Co wybrać?
- Do 1-2 tysięcy produktów: MySQL FULLTEXT albo wtyczka w rodzaju Relevanssi lub SearchWP. Koniecznie zadbaj o wyszukiwanie po SKU i normalizację polskich znaków.
- Kilka do kilkudziesięciu tysięcy produktów, potrzebne filtry i tolerancja literówek: Meilisearch lub Typesense; jeśli polska odmiana jest kluczowa, Elasticsearch lub OpenSearch z analizatorem dla polskiego.
- Duży katalog, wiele filtrów, B2B z kodami produktów: Elasticsearch, OpenSearch lub Manticore, z przemyślaną synchronizacją danych.
- Brak zespołu technicznego i liczy się czas: SaaS, ale policz koszt przy realnym ruchu, a nie przy planie startowym.
Niezależnie od silnika najwięcej daje praca na danych: uzupełnione atrybuty, synonimy dopisywane na podstawie raportu wyszukiwań bez wyników i sensowna kolejność (produkty dostępne i bestsellery wyżej). Raport fraz, które nic nie zwróciły, to zresztą najtańsze źródło wiedzy o tym, czego klienci szukają, a czego nie macie w ofercie. Taki raport łatwo zbudować np. w PostHog.
A gdzie w tym wszystkim AI?
Wszystkie opisane rozwiązania szukają słów. Tymczasem klient coraz częściej opisuje potrzebę: „coś ciepłego na rower w listopadzie”, „prezent dla taty, który lubi grillować”. Żadna z opisanych metod nie zamieni tego na „rękawiczki rowerowe zimowe”. Tu wchodzi wyszukiwanie wektorowe oparte na modelach AI, czyli wyszukiwanie po znaczeniu, a nie po słowach. Coraz częściej stosuje się też połączenie obu podejść. Co ciekawe, większość silników z tego artykułu (Elasticsearch, OpenSearch, Manticore, Meilisearch, Typesense, a także PostgreSQL z rozszerzeniem pgvector) potrafi już przechowywać i przeszukiwać wektory. Jak zbudować to w praktyce, pokażemy w kolejnym artykule z serii o AI w sklepach internetowych.



