Solr i autocomplete (cz. 2)

W poprzedniej części pokazałem w jaki sposób można wykorzystać mechanizm facetingu, aby zrealizować funkcjonalność autocomplete. Dzisiaj postaram pokazać jak wykorzystać komponent nazwany Suggest i za jego pomocą zrealizować funkcjonalność podpowiedzi.

Na początek

Jedna rzecz, którą należy powiedzieć – Suggest component nie jest dostępny w Solr w wersji 1.4.1 i niższych. Aby móc zacząć wykorzystywać ten komponent konieczne jest pobranie mininum wersji 3_x z repozytorium SVN.

Konfiguracja

Zanim przejdziemy do konfiguracji indeksu musimy zdefiniować komponent. A więc zaczynamy od zdefiniowania nowego komponentu wyszukiwania:

<searchComponent name="suggest" class="solr.SpellCheckComponent">
 <lst name="spellchecker">
  <str name="name">suggest</str>
  <str name="classname">org.apache.solr.spelling.suggest.Suggester</str>
  <str name="lookupImpl">org.apache.solr.spelling.suggest.tst.TSTLookup</str>
  <str name="field">name_autocomplete</str>
 </lst>
</searchComponent>

Warto wspomnieć, iż komponent Suggester oparty jest na solr.SpellCheckComponent dlatego konfiguracja wygląda tak jak powyżej. Mamy tutaj trzy ważne informacje:

  • name – nazwa komponentu.
  • lookupImpl – obiekt, który będzie obsługiwał wyszukiwanie. W tym momencie mamy dwie możliwości korzystanie z klasy TSTLookup lub JasperLookup. Ta pierwsza charakteryzuje się jednak większą wydajnością.
  • field – pole na podstawie, którego będą generowane podpowiedzi.

Dodajmy teraz odpowiedni handler, który będzie miał zapisaną odpowiednią konfigurację:

<requestHandler name="/suggest" class="org.apache.solr.handler.component.SearchHandler">
 <lst name="defaults">
  <str name="spellcheck">true</str>
  <str name="spellcheck.dictionary">suggest</str>
  <str name="spellcheck.count">10</str>
 </lst>
 <arr name="components">
  <str>suggest</str>
 </arr>
</requestHandler>

Dość prosta konfiguracja, która dla handlera definiuje dodatkowy komponent oraz mówi Solr, że maksymalna ilość pokazywanych podpowiedzi wynosi 10, ma być wykorzystywany spellchecker (a dokładniej Suggester) oraz, że słownik na podstawie, którego ma być realizowane podpowiadanie nazywa się suggest, czyli dokładnie tak samo jak nasz zdefiniowany komponent.

Indeks

Załóżmy, że nasz dokument składa się z 3 pól: identyfikatora, nazwy i opisu. Podpowiadanie realizujemy na podstawie pola przechowującego nazwę. Nasz indeks mógłby wyglądać nastęująco:

<field name="id" type="string" indexed="true" stored="true" multiValued="false" required="true"/>
<field name="name" type="text" indexed="true" stored="true" multiValued="false" />
<field name="name_autocomplete" type="text_auto" indexed="true" stored="true" multiValued="false" />
<field name="description" type="text" indexed="true" stored="true" multiValued="false" />

Dodatkowo dochodzi następująca definicja kopiowania pola:

<copyField source="name" dest="name_autocomplete" />

Podpowiadanie pojedynczych słów

Aby zrealizować podpowiadanie pojedynczych słów nasz typ text_autocomplete powinien zostać zdefiniowany w następujący sposób:

<fieldType class="solr.TextField" name="text_auto" positionIncrementGap="100">
 <analyzer>
  <tokenizer class="solr.WhitespaceTokenizerFactory"/>
  <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="1"/>
  <filter class="solr.LowerCaseFilterFactory"/>
 </analyzer>
</fieldType>

Podpowiadanie fraz

Aby zrealizować podpowiadanie całych fraz nasz typ text_autocomplete powinien zostać zdefiniowany w następujący sposób:

<fieldType class="solr.TextField" name="text_auto">
 <analyzer>
  <tokenizer class="solr.KeywordTokenizerFactory"/>
  <filter class="solr.LowerCaseFilterFactory"/>
 </analyzer>
</fieldType>

Jeżeli chcemy podpowiadać całe frazy warto zastanowić się nad własną klasą odpowiedzialną za konwersję zapytań.

Budowanie słownika

Przed skorzystaniem z komponentu należy wybudować jego indeks. W tym celu wysyłamy następującą komendę:

/suggest?spellcheck.build=true

Zapytania

Teraz dochodzimy do wykorzystania komponentu. W celu pokazania jak wygląda wykorzystanie komponentu, zdecydowałem się na drugi wariant, czyli pełne frazy. Zadając zapytanie:

/suggest?q=dys

dostajemy następujące podpowiedzi:

<?xml version="1.0" encoding="UTF-8"?>
<response>
 <lst name="responseHeader">
  <int name="status">0</int>
  <int name="QTime">0</int>
 </lst>
 <lst name="spellcheck">
  <lst name="suggestions">
   <lst name="dys">
    <int name="numFound">4</int>
    <int name="startOffset">0</int>
    <int name="endOffset">3</int>
    <arr name="suggestion">
     <str>dysk twardy</str>
     <str>dysk twardy samsung</str>
     <str>dysk twardy seagate</str>
     <str>dysk twardy toshiba</str>
    </arr>
   </lst>
  </lst>
 </lst>
</response>

Na koniec

W kolejnej części dotyczącej funkcjonalności autocomplete zmodyfikujemy trochę wykorzystanie Suggestera i zobaczymy w jaki sposób dodać do mechanizmu słownik, aby jeszcze ulepszyć mechanizm podpowiedzi. Na ostatnią część zostawię sobie porównanie wydajności każdej z metod i sprawdzenia która z metod jest najszybsza w różnych sytuacjach.

13 thoughts on “Solr i autocomplete (cz. 2)

  • 8 grudnia 2010 at 11:50
    Permalink

    Witam,

    Sciagnalem z SVN wersje 3, uruchomilem pod Windows (bez zadnych zmian w konfiguracji):

    java -jar start.jar

    2010-12-08 12:34:02.637:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
    2010-12-08 12:34:02.732:INFO::jetty-6.1.26
    2010-12-08 12:34:02.767:INFO::Started SocketConnector@0.0.0.0:8983

    I po wklepaniu http://localhost:8983/solr/admin pojawia sie 404 :/ Zadnej informacji w logach nie ma 🙁 Czy ktos mial podobny problem?

    Reply
  • 8 grudnia 2010 at 12:05
    Permalink

    Nie używam windows, ale:
    – próbowałeś dodać ‚/’ na końcu adresu?
    – na pewno nie ma nic w logach? to co przedstawiłeś informuje tylko, że kontener jetty się podniósł, a nie, że nie było problemów z aplikacją
    – nie masz przypadkiem spacji w nazwie katalogu, w którym to zainstalowałeś?

    Generalnie wersja3 z wczoraj jeszcze działała poprawnie 😉

    Reply
  • 8 grudnia 2010 at 14:08
    Permalink

    Dzieki. Juz sobie poradzilem. Dziwne, ale po sciagnieciu paczki (nightbuilt) dziala ok, a po sciagnieciu prosto z SVN-a nie chcialo 😉

    Niemniej jednak dzieki za odpowiedz.

    Reply
  • 9 grudnia 2010 at 09:29
    Permalink

    Niestety, ten komponent nie dziala jak powinien :/ Podpowiadanie calych fraz jest ok, ale DOPOKI fraza nie zostanie oddziona spacja. Wowczas dokonuje podwojnego wyszukiwania.

    Czyli w tym przypadku bedzie po wpisaniu „dysk tw” zwroci sugestie dla slowa „dysk” oraz „tw” (osobno!).

    Reply
  • 9 grudnia 2010 at 09:32
    Permalink

    Sprawdź jak masz zdefiniowane pole, które używasz do podpowiedzi, bo jeżeli masz oparte o typ który ma inny tokenizer niż solr.KeywordTokenizerFactory to na pewno podzieli frazę na słowa.

    Reply
  • 9 grudnia 2010 at 16:21
    Permalink

    Natomiast w konfiguracji:

    suggest
    org.apache.solr.spelling.suggest.Suggester
    org.apache.solr.spelling.suggest.tst.JasperLookup
    text_suggest
    true

    I dziala ladnie pod warunkiem, ze fraza jest np. „dy”. Wtedy zwraca „dysk twardy”, „dysk komputerowy” itp. Czyli na tym etapie jest ok.

    Ale gdy fraza jest „dysk tw” to oczekuje wynikow: „dysk twardy”, dysk twardy samsung”; a tymczasem solr zwraca mi podpowiedzi osobno, dla slow „dysk” jak i „tw”

    Reply
  • 9 grudnia 2010 at 16:24
    Permalink

    No i wycielo mi czesc komentarza 😉 Chcialem napisac, ze pole MAM zdefiniowane z tokenizerem solr.KeywordTokenizerFactory.

    I dziala ok, jezeli we frazie nie ma dwoch slow oddzielonych spacja.

    Reply
  • 10 grudnia 2010 at 19:01
    Permalink

    Hmm… dziwne zachowanie, postaram się do tego zajrzeć jutro i dam znać jak to wygląda. Nie pamiętam, abym obserwował takie zachowanie.

    Reply
  • 30 lipca 2011 at 23:10
    Permalink

    Hmm komentarz mi się zgubił – moim zdaniem jedynym sposobem, aby zapobiec takiemu zachowaniu jak opisujesz jest użycie własnego query convertera, ale mogę się mylić.

    Reply
  • 21 lutego 2012 at 11:21
    Permalink

    Wszystko fajnie, prawie…;) Mam taki problem, że wpisując np. audi, chciałbym dostać podpowiedzi również „audi a3”, „audi a4”. Dlatego utworzyłem sobie copyField, gdzie pcham marke i model, ale wyszukiwanie po tym zwraca tylko dopasowanie konkretne? Jakieś sugestie co powinienem dodać, może jakaś konfiguracja do samego spellcheckera? Byłbym wdzięczny.

    Reply
  • 8 marca 2012 at 12:54
    Permalink

    A jak zrealizować takie coś w Solritas?

    Reply
    • 8 marca 2012 at 15:23
      Permalink

      Trzeba zmodyfikować szablony velocity i wzbogacić je o wywołania ajaxowe.

      Reply
  • Pingback:Solr i autocomplete (cz. 3) | 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.