Pełnotekstowe wyszukiwanie w PHP za pomocą Xapiana

Opis i przykładowe skrypty biblioteki Xapian i rozszerzenia dla PHP umożliwiającego indeksowanie i pełnotekstowe przeszukiwanie zaindeksowanych dokumentów z poziomu kodu PHP.

Xapian to biblioteka do pełnotekstowego wyszukiwania danych wykorzystująca własne indeksy. Dzięki rozszerzeniom dostępnym dla wielu języków (PHP, Python, Ruby, Java itd.) można korzystać z tej biblioteki w różnych projektach. Wykorzystywana jest przez Die Zeit, Gmane, serwisy Debiana, czy była/jest wykorzystywana przez del.ico.us. Oferuje bardzo dobrą wydajność i jest mniej wymagająca sprzętowo i aplikacyjne od serwera SOLR.

Główne możliwości i zalety Xapiana to:
  • Otwarte oprogramowanie na licencji GPL
  • Obsługa unikodu, przechowywanie danych w indeksach w kodowaniu utf-8
  • Działa na wielu systemach (MS Windows, Linux, Mac OS X, FreeBSD, NetBSD, OpenBSD, Solaris, HP-UX, Tru64, IRIX)
  • Napiany w C++ z licznymi rozszerzeniami w innych językach
  • Ocena dopasowania wyszukanych wpisów do szukanej frazy
  • Przeszukiwanie fraz - użytkownik może szukać wyrazów pojawiających się w określonej frazie
  • Operatory boolowskie w wyszukiwanych frazach (np. "programowanie NOT perl")
  • Obsługa słowotwórstwa i wykrywanie różnych odmian wyrazów na bazie reguł danego języka (Danish, Dutch, English, Finnish, French, German, Hungarian, Italian, Norwegian, Portuguese, Romanian, Russian, Spanish, Swedish, Turkish)
  • Wyszukiwanie z wildcardem xap*n
  • Sugerowanie poprawnej pisowni szukanej frazy na podstawie zaindeksowanych wyrazów
  • Obsługuje pliki danych większe od 2GB. Format niezależny od systemu operacyjnego
  • Obsługa jednoczesnej aktualizacji i wyszukiwania
  • Dołączona aplikacja Omega potrafiąca indeksować różne formaty dokumentów: HTML, PHP, PDF, PostScript, OpenOffice/StarOffice, OpenDocument, Microsoft Word/Excel/Powerpoint/Works, Word Perfect, AbiWord, RTF, DVI, Perl POD, jak i dane z dowolnej bazy danych obsługiwanej przez moduł Perla DBI.

Instalacja Xapiana i rozszerzenia PHP

W przypadku dystrybucji Linuksa Xapian powinien być dostępny na liście pakietów. Będziemy potrzebować także pakiet xapian-bindings zawierający rozszerzenie dla PHP (w niektórych dystrybucjach ten pakiet może być rozbity na poszczególne języki, np. xapian-bindings-php). Instalujemy oba pakiety. Następnie do php.ini dodajemy rozszerzenie:

extension=xapian.so;
Po restarcie serwera Apache informacja o Xapianie powinna pojawić się w phpinfo.

Dla innych systemów, lub dystrybucji nie posiadających Xapiana w repozytoriach pozostają pakiety i źródła ze strony projektu.

Wykorzystanie Xapiana w PHP

Zaprezentuję tutaj dwa proste skrypty do indeksowania i wyszukiwania zaindeksowanych danych. Do ciebie będzie należeć wykorzystanie zaprezentowanego API do indeksowania jakiś rzeczywistych, sensownych danych :) W przygotowaniu jest także nakładkowa biblioteka dla Zend Framework (które będzie opierać się na opisywanym binarnym rozszerzeniu i będzie ono potrzebne). Poniżej zaprezentowałem czyste API Xapiana w PHP.

Indeksowanie danych polega na zapisie odpowiednio obrobionych danych w indeksie Xapiana - zbiorze plików w podanym katalogu. Oto skrypt umożliwiający zaindeksowanie podanej frazy:
<?php

include "xapian.php";

try {
	// Otwieramy bazę danych lub tworzymy jeżeli nie istnieje
	$database = new XapianWritableDatabase('/ścieżka/do/xapian-db', Xapian::DB_CREATE_OR_OPEN);
	
	$indexer = new XapianTermGenerator();
	// wybieramy język do słowotwórstwa
	$stemmer = new XapianStem("english");
	$indexer->set_stemmer($stemmer);
	$art = 'To jest jakiś artykuł o PHP';
	
	$doc = new XapianDocument();
	$doc->set_data($art);
	
	$indexer->set_document($doc);
	$indexer->index_text($art);
	
	// dodajemy dokument do indeksu
	$database->add_document($doc);
	
	// zamykamy połączenie z indeksem Xapiana
	$database = Null;
	print 'Dodane';
} catch (Exception $e) {
    print $e->getMessage() . "
";
    exit(1);
}
Gdzie:
include "xapian.php";
To załączenie klasy Xapiana dostarczanej wraz z xapian-bindings. Powinna być ona w ścieżce przeszukiwania interpretera. Jeżeli skrypt nie może jej załączyć - zobacz zawartość pakietu i skopiuj ten plik do katalogu z własnym skryptem.

Następnie otwieramy połączenie z indeksem (bazą) Xapiana. Jeżeli baza nie istnieje to zostanie stworzona (wymagane prawa zapisu w katalogu nadrzędnym). Po otworzeniu połączenia z indeksem wybieramy język (w tym przypadku angielski, nie ma niestety oficjalnego polskiego stemmera) i możemy indeksować "dokument", w tym przypadku zwykły łańcuch. Możesz zaindeksować dla testów kilka podobnych fraz.

Wyszukiwanie w Xapianie może przebiegać na wiele sposobów. Poniżej przedstawiłem skrypt wykonujący standardowe wyszukanie najbardziej pasujących dokumentów dla podanej frazy:
<?php
include 'xapian.php';

try {
    $database = new XapianDatabase('/ścieżka/do/xapian-db');
    $enquire = new XapianEnquire($database);

    // wyszukiwana fraza
    $query_string = 'PHP';

    $qp = new XapianQueryParser();
    $stemmer = new XapianStem("english");
    $qp->set_stemmer($stemmer);
    $qp->set_database($database);
    $qp->set_stemming_strategy(XapianQueryParser::STEM_SOME);
    $query = $qp->parse_query($query_string);
    print "Parsed query is: {$query->get_description()}
";

    // Zwróć 10 najlepszych wyników
    $enquire->set_query($query);
    $matches = $enquire->get_mset(0, 10);

    // Wyświetl wyniki
    print "{$matches->get_matches_estimated()} results found:
";

    $i = $matches->begin();
    while (!$i->equals($matches->end())) {
	$n = $i->get_rank() + 1;
	$data = $i->get_document()->get_data();
	print "$n: {$i->get_percent()}% docid={$i->get_docid()} [$data]

";
	$i->next();
    }
} catch (Exception $e) {
    print $e->getMessage() . "
";
    exit(1);
}
Powyższy skrypt zwróci listę pasujących dokumentów i współczynnik dopasowania ("relewentności" :D) poszczególnych dokumentów z szukaną frazą. Np.:
Parsed query is: Xapian::Query(php:(pos=1))
3 results found:
1: 100% docid=3 [To jest jakiś artykuł‚ o PHP]

2: 92% docid=1 [To jest jakiś artykuł‚ o programowaniu w PHP 1]

3: 92% docid=2 [To jest jakiś artykuł‚ o programowaniu w PHP 2]
blog comments powered by Disqus

Kategorie

Strony