django full text search za pomoca sphinx
25 kwietnia, 2008
ORM django pozwala na wyszukiwanie pełnotekstowe za pomocą metody search. Niestety jak na razie jest to funkcja dostępna tylko dla bazy MySQL która wyszukiwaniem pełnotekstowym cieszy sie od dawna. PostgreSQL - zalecana baza django posiada wyszukiwanie pełnotekstowe dopiero w wresji 8.3. Niestety wersja 8.3 jest na razie niedostępna w większości dystrybucji (na gentoo jest zamaskowana) przez co zmuszony zostałem do poszukiwania innego rozwiązania. Z google trafiłem na strone projektu django-sphinx - któryy do wyszukiwania pełnotekstowego w django wykorzystuje sphinx'a.
Czym jest sphinx? Najogólniej mówiąc jest to aplikacja która zajmuje się indexowaniem zadanych zapytań z bazy danych i pozwala później na ich wyszukiwanie. Sphinx pozwala na indexowanie tabel zarówno z MySQL jak i PostgreSQL - mnie z wiadomych przyczyn interesował bardziej ten drugi. Na swojej stronie chwalą się że ich aplikacja jest wykorzystywana przez pokaźną liczbę stron - w tym główne forum phpbb.com, tracker (a tutaj to pewnie co druga akcja użytkownika to wyszukiwanie), tracker mininova.org (podobniez 3-5 milionów wyszukiwań dziennie). Nie znam niestety testów wydajnościowych porównujących bazodanowe mechanizmy full text search ze sphinxem - aczkolwiek postaram się zrobić w najbliższych dniach (mam nawet ładną tabelkę do przeindexowania do testów ;) ).
django vs sphinx
A teraz krótkie howto jak zaimplementować sphinx we własnej aplikacji django.
Po zainstalowaniu sphinxa musimy udać się do /etc/ i edytować sphinx.conf. Dla przykładu definicja indexu do tabeli z komentarzami:
source baza
{
type = pgsql
sql_host = localhost
sql_user = login
sql_pass = haslo
sql_db = baza
sql_port = nshot
}
source komentarze_komentarze : baza
{
sql_query = \
SELECT id, autor_id, extract('epoch' from data_publikacji) \
AS data_publikacji, \
CASE WHEN is_main THEN 1 ELSE 0 END AS is_main, \
CASE WHEN zablokowany THEN 1 ELSE 0 END AS zablokowany, tresc\
FROM komentarze_komentarze
sql_attr_uint = autor_id
sql_attr_timestamp = data_publikacji
sql_attr_bool = is_main
sql_attr_bool = zablokowany
}
index komentarze_komentarze_index
{
source = komentarze_komentarze
charset_type = utf-8
min_infix_len = 1
enable_star = 1
#usuwa polskie znaki i zamienia na literki
charset_table = 0..9, A..Z->a..z, _, a..z, \
U+0143->n, U+0144->n, \
U+0104->a, U+0105->a, \
U+0106->c, U+0107->c, \
U+0118->e, U+0119->e, \
U+0141->l, U+0142->l, \
U+00D3->o, U+00F3->o, \
U+015A->s, U+015B->s, \
U+0179->z, U+017A->z, \
U+017B->z, U+017C->z
# indexuje polskie znaki
# charset_table = 0..9, A..Z->a..z, _, a..z, \
# U+0143->U+0144, U+0104->U+0105, U+0106->U+0107, U+0118->U+0119, \
# U+0141->U+0142, U+00D3->U+00F3, U+015A->U+015B, U+0179->U+017A, \
# U+017B->U+017C, U+0105, U+0107, U+0119, U+0142, U+00F3, \
# U+015B, U+017A, U+017C, U+0144
min_word_len = 2
path = /var/lib/sphinx/data/baza/komentarze
}
- source baza - definiuje połączenie z bazą dancyh - chyba nie musze wyjaśniać co oznacza który wiersz ;)
- source komentarze_komentarze : baza - definiuje "zapytanie" do indexowania (rozszerza "baze") a w nim:
- sql_query - nie musze wyjaśniać - w seleccie sa CASE - ze wzgledu na BUG z boolean z PostgreSQL
- sql_attr_uint, sql_attr_timestamp, sql_attr_bool - typy pól po których można filtrować wyniki - dla przykładu możemy później przeszukać bazę po komentarzach zablokowanych
- index komentarze_komentarze_index - definicja indexu do przeszukiwania
a w nim:- source - zapytanie ktore indexujemy
- min_infix_len - minimalna długość infixu - chodzi tu o to minimalnie ile znakow pozwala na wyszukiwania "wildcardem"
- enable_star - pozwala na wyszukiwanie "wildcard"
- charset_type - kodowanie znaków
- charset_table - lista dostępnych znaków oraz ścieżka zamieniania - duże na małe litery itp (niezakomentowana opcja usuwa polskie znaki - zakomentowana zmienia duze litery na male)
- min_word_len - minimana długość słowa do zaindexowania
- path - ścieżka gdzie zapiane sa pliki indexu
po przygotowaniu pliku z konfiguracja uruchamiamy polecenie
Które utworzy indexy i pozwoli na wyszukiwanie. Następnie uruchamiamy demon do wyszukiwania:
Jeżeli chcemy przeindexować dane w trakcie musimy wykonac polecenie
Rotuje ono pliki z indexami i następnie restartuje searchd.
Pozostaje teraz tylko połączyć sphinx z django. W tym celu w naszym modelu musimy zaimportować djangosphinx a następnie dopisać index do wyszukiwania
from djangosphinx import SphinxSearch #(...) class Komentarze(models.Model): #(...) search = SphinxSearch(index='komentarze_komentarze_index')
Teraz możemy się cieszyć pełnotekstowym wyszukiwaniem za pomocą polecenia
Komentarze do wpisu "django full text search za pomoca sphinx":
1.
arag0rn napisał(a):
25 kwietnia 2008, 15:43:08
Dla ścisłości, wyszukiwanie pełnotekstowe jest w Postgresie od niepamiętnych czasów, dostępne jako moduł tsearch2 w contribie. Od 8.3 jest jedynie dołączone od razu.
Dodaj komentarz: