Autocomplete i znaki specjalne

Wiele wody upłynęło w Wiśle odkąd ostatni, prawdziwy post pojawił się na solr.pl. Takie z krwi i kości, opisujący jakiś problem i sugerujący rozwiązanie. Mówią, że lepiej późno, niż wcale, więc nadszedł ten dzień, kiedy znów coś publikujemy 🙂 Wracamy dzisiaj do tematu autocomplete opartej o suggestery, faceting lub n-gramy. Ta sama funkcjonalność, różne podejścia, różne metody realizacji.

Dzisiaj przyjrzymy się bardziej rozbudowanej funkcjonalonści autocomplete – takiej, która jest w stanie poradzić sobie ze znakami specjalnymi lub inaczej, znakami niewystępującymi w standardowym zbiorze ASCII.

Autocomplete ze znakami specjalnymi

Załóżmy, że nasze dokumenty, na podstawie których chcemy generować wyniki autocomplete, mają tylko dwa pola – identyfikator i pole name. W polu name możemy napotkać znaki specyficzne dla danego języka, np. takie jak ż, ć lub ę w języku polskim. Co byśmy chcieli to umożliwić generowanie autocomplete dla osób, które nie posiadają klawiatury umożliwiającej wpisanie takich znaków, badź locale, które to umożliwiają w systemie. Zakładamy, iż mamy zaindeksowane następujące dokumenty:

Same nazwy nie są znaczące, ważne jest co chcemy osiągnąć. Chcielibyśmy dostać wszystkie trzy dokumenty wpisując pos lub poś. Czy jest to możliwe? Tak i za chwilę zobaczymy, jak to zrobić.

Przygotowanie konfiguracji kolekcji

Zacznijmy od pliku konfiguracyjnego schema.xml i definicji pól i ich typów. Kompletnie zignorujemy w tym wypadku wyszukiwanie pełno tekstowe i skoncentrujemy się tylko i wyłącznie na funkcjonalności autocomplete. Dodatkowo zakładamy, iż chcemy zwrócić zawsze całą wartość pola name, jeżeli tylko trafimy w jakikolwiek term w polu name. Definicja naszych pól w pliku schema.xml wygląda następująco:

Mamy więc pole id, które jest typu int oraz pole name, które używane jest tylko w celu wyświetlania danych. Pole name_ac to te, z za pomocą którego będziemy generować podpowiedzi autocomplete. Aby ręcznie nie wypełniać pola name_ac skorzystamy z tzw. copyField, który przez analizą skopiuje dane z jednego pola do drugiego (umieszczamy to także w pliku schema.xml):

Typ pola name_ac oparty zostanie o mechanizm ngram, czyli przyrostowe generowanie coraz dłuższego przedrostka wartości występującej w tym polu. Do usunięcia znaków pochodzących spoza standardowej tablicy ASCII skorzystamy z filtra solr.ASCIIFoldingFilterFactory. Oczywiście, filtra potrzebujemy zarówno podczas indeksowania, jak i podczas analizy zapytań. Zatem definicja typu text_ac wyglądać będzie następująco:

Jak widać jedyną różnicą pomiędzy analizą podczas indeksowania, a tą podczas zapytania jest wykorzystanie filtra solr.EdgeNGramFilterFactory w trakcie indeksowania. Powoduje on przyrostowe generowanie przedrostka i umieszczenie tych wartości w danym polu. Filtra tego nie potrzebujemy podczas zadawania zapytań.

Czas testowania

Aby przetestować to co zrobiliśmy uruchomimy Solr w wersji SolrCloud z wbudowanym ZooKeeperem za pomocą następującego polecenia:

Następnie prześlemy konfigurację zawierającą wszystkie nasze zmiany do ZooKeepera używając następującego polecenia:

Jedyne o czym należy pamiętać, aby powyższe polecenie zadziałało to stworzenie konfiguracji (lub jej pobranie z naszego konta Github – konfiguracja), a następnie umieszczenie jej w odpowiednim katalogu.

Następnie tworzymy kolekcję za pomocą bardzo prostego polecenia:

Po poprawnym wykonaniu polecenia, możemy zaindeksować testowe dokumenty z początku wpisu w następujący sposób:

Zadajmy więc dwa zapytania, jedno z literą ś, a drugie z literą s i porównajmy rezultaty. Pierwsze zapytanie wygląda następująco:

Drugie wygląda natomiast tak:

W obu przypadkach korzystamy z parsera Extended DisMax, spójnika logicznego AND (parametr q.op) i ustawiamy pole po którym chcemy szukać na name_ac za pomocą parameteru qf. Dodatkowo mówimy Solr, iż chcemy aby zwrócone zostały tylko pola id oraz name za pomocą parametru fl.

W przypadku obu zapytań wyniki są jednakowe i wyglądają następująco:

Jak widać opisana metoda działa 🙂

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

This site uses Akismet to reduce spam. Learn how your comment data is processed.