Tomasz Tomczyk - Programista PHP, Kraków - Strona główna > programowanie > Wyszukiwanie pełnotekstowe (full-text search) na stronie www.

Wyszukiwanie pełnotekstowe (full-text search) na stronie www.

Listopad 22nd, 2010

W tym artykule chciałbym napomnieć o różnych sposobach zaimplementowania na stronie www wyszukiwarki pełnotekstowej. Nie ma w tym przypadku jedynego słusznego rozwiązania. Wszystko zależy od serwisu na którym wyszukiwarka ma działać.

Zakładamy taką sytuację, że tworzymy sobie serwis w stylu dziennika obywatelskiego. Użytkownicy piszą i zamieszczają na nim swoje artykuły, komentują itd. Do przechowywania danych będziemy używać bazy danych MySQL.

Logiczną sprawą jest zaimplementowanie wyszukiwarki w takim serwisie. Podstawowe funkcjonalności wyszukiwarki to głównie szukanie po tytule, autorze, dacie, kategorii … można by tu jeszcze wymienić parę rzeczy. Zastanówmy się czyż nie fajnym dodatkiem do naszej wyszukiwarki byłaby możliwość wyszukiwania w samej treści artykułu (tak zwane wyszukiwanie pełnotekstowe) ??

Teraz musimy nasz pomysł jakoś zaimplementować w kodzie. Poniżej parę przykładów na jakich rozwiązaniach możemy się oprzeć.

LIKE
Pierwszą myślą jak może przyjść do głowy to użycie do szukania konstrukcji LIKE.
Jeśli ktoś chce wycisnąć ze swojego serwera ostatnie poty i napisać super nie optymalny kod to polecam tą metodę :)
Osobiście proponowałbym odrzucić ten pomysł i pomyśleć chwilę dłużej.

MySQL – fulltext
Kolejną myślą mogło by być użycie wsparcie MySQL do wyszukiwania pełnotekstowego.
Niestety tu też pojawiają się problemy. O ile silnik bazy MyISAM posiada możliwość założenia indeksu pełnotekstowego (fulltext) to niestety najpopularniejszy, przynajmniej według mnie silnik InnoDB wsparcia dla wyszukiwania pełnotekstowego nie posiada :( .
Jest kilka sposobów na obejście tego problemu, np utworzenie specjalnej tabeli do której będziemy kopiować wszystkie teksty umieszczanie na stronie przy użyciu triggerów.
Tym zagadnieniem zajmiemy się jednak kiedy indziej. Dzisiaj chciałbym abyśmy w swoich rozważaniach poszli jeszcze trochę dalej i zapoznali się z innymi możliwościami zaimplementowania fulltexta w naszej wyszukiwarce.

Jak poszukamy sobie trochę w sieci to znajdziemy dwa konkurencyjne rozwiązania które przyjdą nam z pomocą, a mianowicie: Lucene i Sphinx Search. Ogólnie oba rozwiązania bazują na tworzeniu odpowiednich indeksów przy użyciu powyższych technologi.

Lucene
Zostało stworzone przez Douga Cuttinga w javie.

Możliwości:
- indeksowanie zawartości plików wielu formatów np: pdf, doc, email …
- wysoka skalowalność
- funkcjonalność jednoczesnego wyszukiwania i aktualizowania indexu
- wbudowany mechanizm stronicowania

Wymagania systemowe:

  • Java 1.5.x lub nowsza
  • ANT 1.7.0 lub nowszy
  • JUnit 3.8.2 – jeśli chcemy uruchamiać testy

Główne typy pól:
- indeksowane, przechowywane: dane w tym polu podlegają rozbiciu na frazy, które następnie są wykorzystywane przy wyszukiwaniu. Dane są zachowane w indeksie w formie umożliwiającej późniejszy odczyt i prezentację.
- nie indeksowane, przechowywane: dane przechowywane w indeksie nie są indeksowane i rozbijane na frazy. Są przechowywane w formie niezmienionej, służące do wyświetlania i prezentacji wyników wyszukiwania.
- indeksowane, nie przechowywane: dane są rozbijane na frazy i indeksowane, używane wyłącznie do wyszukiwania.
- słowa kluczowe: dane są indeksowane ale nie są rozbijane na frazy, czyli przechowywane są w indeksie w formie orginalnej.

Sphinx
Pomysłodawcą i głównym autorem jest Andrew Aksyonoff. Język programowania to C++.

W pakiet Sphinx’a wchodzą cztery główne moduły: indexer, search, searchd, sphinxapi.
Indexer: główne narzędzie robocze używane do tworzenia pełnotekstowych indeksów.
Search: narzędzie do testowania stworzonych indeksów.
Searchd: jest do demon dzięki któremu zewnętrzne aplikacje mogą się poprzez specjalne api przeszukiwać nasze indeksy.
Sphinxapi: jest to nic innego jak zbiór bibliotek udostępniających api dla różnych języków programowania, w tym również dla PHP.

Co tak naprawdę Sphinx potrafi:
- szybkie indeksowanie (10 – 15 MB/sec)
- szybkie wyszukiwanie (150 – 250 zapytań/sec w indeksie zawierającym ponad 1M wpisów i fizycznym rozmiarze 1.2GB)
- wysoka skalowalność
- obsługuje rozproszone wyszukiwanie
- możliwość użycia go jako silnika bazy MySQL, przez co możemy odwoływać się do danych przy użycia składnie SQL podobnej jak przy zapytaniach do indexu fulltextowego w silniku MyISAM
- obsługa morfologii dla języka angielskiego i rosyjskiego
- natywne wsparcie dla MySQL oraz PostreSQL

Można go uruchomić i skonfigurować pod większością systemów:

  • Linux 2.4.x, 2.6.x (many various distributions)
  • Windows 2000, XP
  • FreeBSD 4.x, 5.x, 6.x, 7.x
  • NetBSD 1.6, 3.0
  • Solaris 9, 11
  • Mac OS X

Wymagania systemowe (środowisko UNIX):

  • kompilator C++
  • make

Następnie pozostaje utworzyć indeksy i używać.
Oczywiście konfiguracja indeksów to temat rzeka, więc pozostawię to jako temat osobnego artykułu.

Inne rozwiązania
Artykuł ten nie wyczerpuje wszystkich sposobów implementacji wyszukiwarki pełnotekstowej.
Kolejne alternatywy:

  • użycie bazy PostgeSQL zamiast MySQL, która ma lepsze wbudowane wsparcie dla wyszukiwania pełnotekstowego.
  • DataparkSearch napisany w C
  • Ferret napisany w Ruby inspirowany Lucene
  • mnoGoSearch napisany w C
  • Xapian napisany w C++
  • i inni …

Tak więc widzimy, że wybór jest naprawdę duży, trzeba tylko odpowiednio poszperać.
Taką ciekawostką jest fakt, że większość rozwiązań jest napisana przez naszych „kolegów” z za Buga :)

Podsumowanie
Oczywiście nie jest powiedziane, że w każdym przypadku używanie Sphinxa lub Lucene jest najlepszym rozwiązaniem. Nie ma sensu strzelanie armatą do muchy. W małych serwisach spokojnie wystarczy rozwiązanie oparte na wbudowanych mechanizmach w bazę danych. Jednak w przypadku gdy nasz serwis agreguje duże ilości danych proponowałbym się poważnie zastanowić nad bardziej zaawansowanym rozwiązaniem.

  1. pkuliga
    Marzec 2nd, 2011 at 01:16 | #1

    Kiedy następne arty?

  2. admin
    Marzec 11th, 2011 at 13:03 | #2

    już niedługo :)

  3. Marzec 21st, 2011 at 23:14 | #3

    Czekamy, czekamy …

  4. kubaw
    Maj 5th, 2011 at 13:20 | #4

    Posucha…

  5. admin
    Maj 11th, 2011 at 14:01 | #5

    cierpliwości :)

  6. Maj 17th, 2011 at 14:46 | #6

    Prosimy o więcej :-)

  7. kubaw
    Maj 27th, 2011 at 16:40 | #7

    Cierpliwość powoli dobiega końca, ileż można czekać?

  8. admin
    Czerwiec 1st, 2011 at 11:26 | #8

    Cierpliwość została nagrodzona – już jest :D

  9. Czerwiec 1st, 2011 at 13:12 | #9

    @admin

    Prezent z okazji Dnia Dziecka :-D

  1. Brak jeszcze trackbacków
Komentarze są zamknięte