Solr i autocomplete (cz. 1)

Niemal każdy z nas widział jak wygląda funkcjonalność autocomplete, czyli podpowiadanie użytkownikowi wyrazów lub całych fraz wyszukiwania. Nic dziwnego więc, że także Solr udostępnia mechanizmy przy pomocy których możemy zbudować takie funkcjonalności. W dzisiejszym wpisie pokażę w jaki sposób można zbudować podpowiadanie przy pomocy facetingu.

Indeks

Załóżmy, że chcemy podpowiadać użytkownikowi nazwy produktów w sklepie internetowym. Załóżmy, że nasz indeks składa się z następujących pól:

A typ text zdefiniowany jest w następujący sposób:

Konfiguracja

Na początku należy zastanowić się co chcemy uzyskać. Czy chcemy aby podpowiadane były tylko poszczególne wyrazy składające się na frazy, czy może jednak pełne nazwy rozpoczynające się na podane przez użytkownika litery. W zależności od naszych wyborów musimy przygotować odpowiednie pole, na podstawie którego będziemy budować podpowiedzi.

Podpowiadanie pojedynczych wyrazów składających się na nazwę

W przypadku podpowiadania pojedynczych wyrazów powinniśmy podpowiadanie oprzeć o pole, które będzie odpowiednio tokenizowane. W naszym przypadku pole name będzie wystarczające. Należy jednak pamiętać, iż jeżeli chcemy korzystać np. ze stemmingu należałoby zdefiniować kolejny typ, który były go pozbawiony, ze względu na to jak taka analiza działa na zawartość pola.

Podpowiadanie pełnych nazw

W przypadku podpowiadania pełnych nazw produktów potrzebujemy innej konfiguracji pola na którym oprzemy podpowiadanie – najlepsze do tego będzie pole nietokenizowane. Nie możemy jednak wykorzystać do tego celu typu string – ze względu na to. W tym celu definiujemy pole następująco:

Typ ten został zdefiniowany w następujący sposób:

Aby nie było konieczności modyfikacji formatu danych dodajemy dodatkowo odpowiednią definicję kopiowania informacji:

Jak to wykorzystać ?

Mając już odpowiednio zaindeksowane dane możemy zacząć korzystanie z Solr. Aby skorzystać z tak przygotowanych danych skorzystać wystarczy dość proste zapytanie:

Gdzie:

  • POLE – pole na jakiego podstawie mamy zamiar realizować podpowiadanie. W naszym przypadku name_auto.
  • ZAPYTANIE_UŻYTKOWNIKA – litery, które wpisał użytkownik.

Warto zauważyć parametr rows=0 dodany po to, aby widoczny był tylko wynik facetingu. Oczywiście nie jest to konieczność.

Na przykład:

Wynik powyższego zapytania mógłby wyglądać następująco:

Dodatkowe możliwości

Warto wspomnieć o dodatkowych możliwościach jakie niesie za sobą ta metoda.

Pierwsza z możliwości to pokazanie użytkownikowi dodatkowych informacji takich jak ilość wyników jaką dostanie użytkownik po wybraniu odpowiedniej podpowiedzi. Jeżeli chcemy pokazywać takie informacje będzie to na pewno ciekawa opcja.

Możliwość wyboru sortowania wyników facetingu, czyli standardowe wykorzystanie parametru facet.sort. W zależności od potrzeb możemy posortować wyniki po ilości dokumentów (domyślne zachowanie, wartość parametru ustawiamy na true) lub alfabetycznie (wartość parametru ustawiamy na false).

Możemy ograniczyć podpowiedzi, aby nie były generowane te, które mają mniejszą, niż określona ilość wyników. Aby skorzystać z tej możliwości należy przekazać w parametrze facet.mincount ilość dokumentów od jakiej mają być pokazywane wyniki.

I jak dla mnie największy plus tej metody – możliwość prostego pobierania podpowiedzi tylko tych, które pasują do zapytania użytkownika oraz dodatkowych parametrów, takich jak np. kategoria w której się znajduje. Na przykład chcemy pokazać podpowiedzi dla użytkownika, który znajduje się w dziale AGD naszego sklepu. Podejrzewamy, że w tej chwili nie będą go interesować produkty typu odtwarzacze DVD i dlatego dodajemy parametr fq=dział:agd (zakładając, że mamy taki dział). Po tak zmodyfikowanym zapytaniu, użytkownik nie dostanie podpowiedzi wygenerowanych z całego indeksu, a zawężone, do tego jaki dział przegląda.

Kilka słów na zakończenie

Jak wiele metod i ta ma swoje plusy i minusy. Plusem tego rozwiązania jest łatwość jego wykorzystania, brak dodatkowych komponentów oraz to, że wyniki podpowiedzi można w bardzo prosty sposób zawężać, aby były generowane tylko z tych dokumentów, które pasują do zapytania wpisanego przez użytkownika. Jako duży plus można zaliczyć pokazywanie ilości dokumentów, jakie dostanie użytkownik wybierając daną podpowiedź (oczywiście przy zachowaniu takich samych parametrów wyszukiwania). Do minusów należy na pewno konieczność posiadania dodatkowych typów i pól obsługujących podpowiedzi, wbrew pozorom dość ograniczone możliwości oraz obciążenie Solr powodowane przez mechanizm facetingu.

W następnym wpisie dotyczącym funkcjonalności autocomplete postaram się rozszerzyć temat i pokazać kolejne metody generowania podpowiedzi za pomocą Solr.

12 thoughts on “Solr i autocomplete (cz. 1)

  • 20 października 2010 at 16:02
    Permalink

    jakoś nie ma searcha na tym blogu o searchu 🙂

    Reply
  • 20 października 2010 at 18:25
    Permalink

    Trafna uwaga. I póki co nie będzie. Ale testowo włączyłem „toto”, które jest standardowo dostępne w CMSie 🙂

    Reply
  • 25 listopada 2010 at 14:06
    Permalink

    „odejrzewamy, że w tej chwili nie będą go interesować produkty typu odtwarzacze DVD i dlatego dodajemy parametr fq=dział:agd (zakładając, że mamy taki dział). Po tak zmodyfikowanym zapytaniu, użytkownik nie dostanie podpowiedzi wygenerowanych z całego indeksu, a zawężone, do tego jaki dział przegląda.”

    Ta opcja dla przykładowego, przedstawionego powyżej, zapytania bez względu na poprawność parametru fq u coś nie działa – lista wyników nie zostaje zawężona. Czy aby na pewno „samotne” fq odfiltrowuje wyniki !?

    Reply
  • 25 listopada 2010 at 14:24
    Permalink

    Te zaszyte w konfiguracji handlerów parametry – proponuję dodać jeszcze dodatkowy parametr – facet.mincount=1 (w sumie do głównego zapytania także), wtedy pokażą się tylko te wyniki, które występują po zawężeniu.

    Dzięki za zwrócenie uwagi, poprawię wpis.

    Reply
  • 25 listopada 2010 at 15:50
    Permalink

    Dzięki za szybką odpowiedź.

    Niestety zastosowanie u mnie facet.mincount=1 nic nie daje ze względu na to, że wszystkie zwracane „podpowiedzi” mają count „0” (co nie jest zgodne z rzeczywistymi wynikami dla danej frazy).

    Trochę inaczej zdefiniowałem „name_auto” tzn. u mnie ma ono multiValued=”true” bo sprawa się tyczy tagów a każda treść może mieć ich wiele. Czy to może powodować problem z błędną ilością wyników !?

    Reply
  • 25 listopada 2010 at 15:59
    Permalink

    Przed odpowiedzią na pytanie – z jakiego query parsera korzystasz – ze standard, czy z dismax’a ?

    Reply
  • 26 listopada 2010 at 16:45
    Permalink

    Dla pewności sprawdzę jeszcze jak to wszystko zachowuje się przy polach wielowartościowych i wtedy napiszę co i jak.

    Reply
  • 27 listopada 2010 at 21:17
    Permalink

    Moim zdaniem, jeżeli count dla danego tagu masz 0, to nie powinieneś podpowiadać tego. Wielowartościowość nie powinna mieć tutaj znaczenia. Zrobiłem mały test:

    schema.xml:
    <fields>
    <field name=”id” type=”string” indexed=”true” stored=”true” multiValued=”false” required=”true”/>
    <field name=”name_auto” type=”text_auto” indexed=”true” stored=”true” multiValued=”true” />
    </fields>

    data.xml:
    <add>
    <doc>
    <field name=”id”>1</field>
    <field name=”name_auto”>Dysk</field>
    <field name=”name_auto”>twardy</field>
    </doc>
    <doc>
    <field name=”id”>2</field>
    <field name=”name_auto”>Dysk</field>
    <field name=”name_auto”>twardy</field>
    <field name=”name_auto”>samsung</field>
    </doc>
    <doc>
    <field name=”id”>3</field>
    <field name=”name_auto”>Dysk</field>
    <field name=”name_auto”>twardy</field>
    <field name=”name_auto”>toshiba</field>
    </doc>
    <doc>
    <field name=”id”>4</field>
    <field name=”name_auto”>Dysk</field>
    <field name=”name_auto”>twardy</field>
    <field name=”name_auto”>seagate</field>
    </doc>
    </add>

    Zapytanie:
    http://localhost:8983/solr/select?fl=id,name_auto&rows=0&q=*:*&facet=true&facet.field=name_auto&facet.mincount=1&facet.prefix=dys

    Wynik:
    <?xml version=”1.0″ encoding=”UTF-8″?>
    <response>
    <lst name=”responseHeader”>
    <int name=”status”>0</int>
    <int name=”QTime”>0</int>
    <lst name=”params”>
    <str name=”facet”>true</str>
    <str name=”fl”>id,name_auto</str>
    <str name=”facet.mincount”>1</str>
    <str name=”q”>*:*</str>
    <str name=”facet.prefix”>dys</str>
    <str name=”facet.field”>name_auto</str>
    <str name=”rows”>0</str>
    </lst>
    </lst>
    <result name=”response” numFound=”4″ start=”0″/>
    <lst name=”facet_counts”>
    <lst name=”facet_queries”/>
    <lst name=”facet_fields”>
    <lst name=”name_auto”>
    <int name=”dysk”>4</int>
    </lst>
    </lst>
    <lst name=”facet_dates”/>
    </lst>
    </response>

    Jak widzisz, pomimo wielowartościowości Solr nie miał problemów z wyliczeniem ilości dokumentów i wygenerowaniem podpowiedzi. Najlepiej wklej przykład danych i definicję pól ze schemy oraz zapytanie, wtedy będę mógł pomóc bardziej konkretnie.

    Reply
  • Pingback:Solr i autocomplete (cz. 2) | Solr Enterprise Search

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.