Sphinx: Różnice pomiędzy wersjami
(→Konfiguracja cz. 2) |
|||
Linia 16: | Linia 16: | ||
Poniżej znajduje się przykład indeksowania wiadomości. | Poniżej znajduje się przykład indeksowania wiadomości. | ||
− | ==== Konfiguracja cz. 1==== | + | ==== Indeksowanie ==== |
+ | |||
+ | ===== Konfiguracja cz. 1===== | ||
Dla wygodniejszej pracy zalecane jest stworzenie paru katalogów, na przykład: | Dla wygodniejszej pracy zalecane jest stworzenie paru katalogów, na przykład: | ||
− | * <code class="directory">wyszukiwanie/dane/wiadomosci</code> - wszystkie artykuły; | + | * <code class="directory">~/wyszukiwanie/dane/wiadomosci</code> - wszystkie artykuły; |
− | * <code class="directory">wyszukiwanie/index/wiadomosci</code> - wszystkie pliki stworze podczas indeksowania; | + | * <code class="directory">~/wyszukiwanie/index/wiadomosci</code> - wszystkie pliki stworze podczas indeksowania; |
− | * <code class="directory">wyszukiwanie/conf</code> - pliki konfiguracyjne; | + | * <code class="directory">~/wyszukiwanie/conf</code> - pliki konfiguracyjne; |
− | * <code class="directory">wyszukiwanie/bin/wiadomosci</code> - skrypty potrzebne do indeksowania. | + | * <code class="directory">~/wyszukiwanie/bin/wiadomosci</code> - skrypty potrzebne do indeksowania. |
− | Plik konfiguracyjny <code class="directory">wyszukiwanie/conf/sphinx.conf</code>: | + | Plik konfiguracyjny <code class="directory">~/wyszukiwanie/conf/sphinx.conf</code>: |
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
source wiadomosci | source wiadomosci | ||
Linia 41: | Linia 43: | ||
* <code>xmlpipe_command = ~/wyszukiwanie/bin/news/xmlout.sh</code> - jest to komenda, która zostanie uruchomiana aby wypisała na standardowe wyjście wszystkie dokumenty XML jako jeden dokument. | * <code>xmlpipe_command = ~/wyszukiwanie/bin/news/xmlout.sh</code> - jest to komenda, która zostanie uruchomiana aby wypisała na standardowe wyjście wszystkie dokumenty XML jako jeden dokument. | ||
− | ==== Pola i atrybuty ==== | + | ===== Pola i atrybuty ===== |
Zawartość dokumentu, która potrzebuje być zindeksowana nazywana jest polem (field). Intuicyjnie dla wiadomości (newsów) cała treść artykułu jest polem. | Zawartość dokumentu, która potrzebuje być zindeksowana nazywana jest polem (field). Intuicyjnie dla wiadomości (newsów) cała treść artykułu jest polem. | ||
Linia 68: | Linia 70: | ||
Powyższa linijka sprawi, że indexer da sobie radę ze streamem XML w UTF-8. | Powyższa linijka sprawi, że indexer da sobie radę ze streamem XML w UTF-8. | ||
− | ==== XML ==== | + | ===== XML ===== |
Poniżej są 2 przykładowe artykuły z następującą treścią: | Poniżej są 2 przykładowe artykuły z następującą treścią: | ||
Linia 127: | Linia 129: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | ==== Konfiguracja cz. 2 ==== | + | ===== Konfiguracja cz. 2 ===== |
− | Druga część konfiguracji w pliku <code class="directory">wyszukiwanie/conf/sphinx.conf</code>: | + | Druga część konfiguracji w pliku <code class="directory">~/wyszukiwanie/conf/sphinx.conf</code>: |
<syntaxhighlight lang="text"> | <syntaxhighlight lang="text"> | ||
Linia 160: | Linia 162: | ||
− | ==== | + | ===== Uruchamianie indeksowania ===== |
Poniższa komenda uruchomi indeksowanie | Poniższa komenda uruchomi indeksowanie | ||
Linia 169: | Linia 171: | ||
==== Wyszukiwanie ==== | ==== Wyszukiwanie ==== | ||
+ | Za wyszukiwanie odpowiada daemon <code>searcgd</code>. Poniżej znajduje się przykład konfiguracji oraz sposób jego uruchomienia. | ||
+ | ===== Konfiguracja ===== | ||
+ | Konfiguracja tak jak we wcześniejszych częsciach znajduje się w pliku <code class="directory">~/wyszukiwanie/conf/sphinx.conf</code>: | ||
+ | <syntaxhighlight lang="text"> | ||
searchd | searchd | ||
{ | { | ||
Linia 189: | Linia 195: | ||
max_filter_values = 4096 | max_filter_values = 4096 | ||
max_batch_queries = 32 | max_batch_queries = 32 | ||
− | workers = | + | workers = 4 |
dist_threads = 4 | dist_threads = 4 | ||
} | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Większość z opcji jest ustawiona standardowo i nie wymaga zrozumienia. | ||
+ | |||
+ | ===== Uruchamianie daemona ===== | ||
+ | |||
+ | Aby uruchomić daemon <code>searchd</code> należy skorzystać z polecenia: | ||
+ | searchd -c ~/wyszukiwanie/conf/sphinx.conf | ||
+ | |||
+ | ===== Wyszukiwanie za pomocą PHP ===== | ||
+ | |||
+ | Sphinx search ma bardzo dużo klientów, jednym z nich jest PHP API. Poniżej znajduje się przykład: | ||
+ | <syntaxhighlight lang="php"> | ||
+ | <?php header('Content-Type: text/plain; charset=iso-8859-1'); | ||
+ | include('sphinxapi.php'); | ||
+ | $cl = new SphinxClient(); | ||
+ | $cl->SetServer("/home/''login''/wyszukiwanie/searchd.sock"); | ||
+ | $cl->SetSortMode(SPH_SORT_RELEVANCE); | ||
+ | $results = (int)$_GET['results']; | ||
+ | $offset = (int)$_GET['offset']; | ||
+ | $cl->SetLimits($offset, $results); | ||
+ | $min_date = (int)$_GET['mindate']; | ||
+ | $max_date = (int)$_GET['maxdate']; | ||
+ | $cl->SetFilterRange('date', $min_date, $max_date); | ||
+ | if ($_GET['mode'] == 'All') { | ||
+ | $cl->SetMatchMode(SPH_MATCH_ALL); | ||
+ | } | ||
+ | else if ($_GET['mode'] == 'Any') { | ||
+ | $cl->SetMatchMode(SPH_MATCH_ANY); | ||
+ | } | ||
+ | else if ($_GET['mode'] == 'Phrase') { | ||
+ | $cl->SetMatchMode(SPH_MATCH_PHRASE); | ||
+ | } | ||
+ | else if ($_GET['mode'] == 'Extended') { | ||
+ | $cl->SetMatchMode(SPH_MATCH_EXTENDED); | ||
+ | } | ||
+ | $keywords = preg_replace("/"/", "\"", $_GET['keywords']); | ||
+ | $result = $cl->Query( $keywords, $_GET['index'] ); | ||
+ | if ( $result === false ) { | ||
+ | echo "ERROR|Query failed: " . $cl->GetLastError() . "\n"; | ||
+ | } | ||
+ | else { | ||
+ | if ( $cl->GetLastWarning() ) { | ||
+ | echo "WARNING|" . $cl->GetLastWarning() . "\n"; | ||
+ | } | ||
+ | if ( ! empty($result['matches']) ) { | ||
+ | print_r($result['matches']); | ||
+ | } | ||
+ | } | ||
+ | ?> | ||
+ | </syntaxhighlight> | ||
+ | i przykładowe użycie za pomocą curl: | ||
+ | curl "http://localhost/search.php?keywords=Anna+Team&results=20&offset=0&mindate=20090101&maxdate=20140806&mode=Phrase&index=news" | ||
=== Odnośniki Zewnętrzne === | === Odnośniki Zewnętrzne === | ||
* [http://sphinxsearch.com/ Sphinx Search] | * [http://sphinxsearch.com/ Sphinx Search] | ||
[[Kategoria:Bazy danych]] | [[Kategoria:Bazy danych]] |
Wersja z 13:56, 27 lip 2015
Sphinx to otwarty, w pełni tekstowy serwer wyszukiwania stworzony w C++ i udostępniony na licencji GPLv2. Najczęściej jest wykorzystywany do indeksowania danych z baz MySQL, PostreSQL i specjalnie sformatowanych plików xml.
Spis treści
Elementy Sphinxa
Sphinx składa się z następujących elementów:
-
indexer
- narzędzie do tworzenia pełnotekstowych indeksów (indices); -
searchd
- demon do przeszukiwania indeksów przez zewnętrzne aplikacji (np. skrypty www komunikujące się przez API, MySQ z SphinxSE itp.), jest uruchomiony na serwerze; -
sphinxapi
- zbiór bibliotek udostępniających API Sphinxa dla PHP, Pythona, Javy, Perla, czy Rubiego; -
spelldump
- proste narzędzie do wydobywania pozycji ze słownika ispell lub MySpell służące do dostosowania indexu; -
indextool
- program narzędziowy do zrzucania rozmaitych; -
wordbreaker
- program służący do rozdzielania połączonych wyrazów na oddzielne.
Przykład
Poniżej znajduje się przykład indeksowania wiadomości.
Indeksowanie
Konfiguracja cz. 1
Dla wygodniejszej pracy zalecane jest stworzenie paru katalogów, na przykład:
-
~/wyszukiwanie/dane/wiadomosci
- wszystkie artykuły; -
~/wyszukiwanie/index/wiadomosci
- wszystkie pliki stworze podczas indeksowania; -
~/wyszukiwanie/conf
- pliki konfiguracyjne; -
~/wyszukiwanie/bin/wiadomosci
- skrypty potrzebne do indeksowania.
Plik konfiguracyjny ~/wyszukiwanie/conf/sphinx.conf
:
source wiadomosci { type = xmlpipe xmlpipe_command = ~/wyszukiwanie/bin/wiadomosci/xmlout.sh xmlpipe_field = content xmlpipe_attr_string = url xmlpipe_attr_uint = date xmlpipe_fixup_utf8 = 1s }
-
source wiadomosci
- definicja źródła indeksowania identyfikowana jako wiadomosci. -
type = xmlpipe
- definicja typu źródła indeksowania, tutaj to dokument XML, który jest przekazywany za pomocą pipe do indexera. -
xmlpipe_command = ~/wyszukiwanie/bin/news/xmlout.sh
- jest to komenda, która zostanie uruchomiana aby wypisała na standardowe wyjście wszystkie dokumenty XML jako jeden dokument.
Pola i atrybuty
Zawartość dokumentu, która potrzebuje być zindeksowana nazywana jest polem (field). Intuicyjnie dla wiadomości (newsów) cała treść artykułu jest polem.
Atrybut jest informacją powiązaną z artykułu.
Gdy jedno z wyszukiwań dopasuje szukane frazy do fraz zindexowanych we wszystkich dokumentach to dla każdego dopasowanego artykułu zwracany jest sam dokument wraz z jego atrybutami.
xmlpipe_field = content xmlpipe_attr_string = url xmlpipe_attr_uint = date
Powyższa zawartość określa:
- Tekst w tagu XML content będzie traktowany jako pole (field), więc będzie indeksowane
- Tekst w tagu XML url będzie traktowany jak atrybut tekstowy (string).
- Tekst w tagu XML date będzie traktowany jak atrybut numeryczny (numerical).
Numeryczny atrybut daty wydaje się nieintuicyjny. Natomiast podczas szukania można zdefiniować nie tylko konkretne wartości atrybutów, ale i ich zakresy, które nie działają najlepiej z atrybutem tekstowym.
xmlpipe_fixup_utf8 = 1
Powyższa linijka sprawi, że indexer da sobie radę ze streamem XML w UTF-8.
XML
Poniżej są 2 przykładowe artykuły z następującą treścią:
Gmina Ostrowice w Zachodniopomorskiem może zostać zlikwidowana za długi. Jej zadłużenie trzykrotnie przewyższa roczne dochody.
i
Miasto Słupsk popadło w kłopoty finansowe, po przegranym procesie, który miastu wytoczył wyrzucony z budowy słupskiego aquaparku wykonawca. Miasto ma zapłacić firmie Termochem 24 miliony złotych.
Indexer będzie się spodziewał takiego streamu:
<?xml version="1.0" encoding="utf-8"?> <sphinx:docset> <sphinx:document id="1"> <url>url</url> <date>data</date> <content>Gmina Ostrowice w Zachodniopomorskiem może zostać zlikwidowana za długi. Jej zadłużenie trzykrotnie przewyższa roczne dochody.</content> </sphinx:document> <sphinx:document id="2"> <url>url</url> <date>data</date> <content>Miasto Słupsk popadło w kłopoty finansowe, po przegranym procesie, który miastu wytoczył wyrzucony z budowy słupskiego aquaparku wykonawca. Miasto ma zapłacić firmie Termochem 24 miliony złotych.</content> </sphinx:document> </sphinx:docset>
Rzeczy warte zauważenia:
- każdy dokument musi mieć numeryczne id,
- wszystkie tagi niezaczynające się od sphinx: zostały zdefiniowane w pliku konfiguracyjnym.
Kolejnym etapem jest stworzenie skryptu ~/wyszukiwanie/bin/wiadomosci/xmlout.sh
, który wygeneruje powyższy XML. Poniżej znajduje się przykładowy:
#!/bin/bash echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>" echo "<sphinx:docset>" counter=0 for filename in `find ~/wyszukiwanie/dane/wiadomosci/ -type f` do url=`head -n 2 $filename | tail -n 1` url=`echo $url | sed 's/&/%26/g' ` date=`head -n 1 $filename | sed 's/\-//g'` counter=`expr $counter + 1` lines=`wc -l $filename | awk '{print $1}'` lines=`expr $lines - 2` echo "<sphinx:document id=\"$counter\">" echo "<url>$url</url>" echo "<date>$date</date>" echo -n "<content>" tail -n $lines $filename | sed 's/&/and/g' echo "</content>" echo "</sphinx:document>" done echo "</sphinx:docset>"
Konfiguracja cz. 2
Druga część konfiguracji w pliku ~/wyszukiwanie/conf/sphinx.conf
:
index wiadomosci { source = wiadomosci path = ~/wyszukiwanie/index/wiadomosci/idx docinfo = extern mlock = 0 morphology = stem_en, soundex min_word_len = 1 charset_type = utf-8 html_strip = 1 }
Ta część odpowiada za definicję indeksowania wiadomości. Określa w jaki sposób indeks ma być stworzony, gdzie przetrzymywany itd.
-
source = wiadomosci
- definicja źródła indeksowania. Źródło wiadomosci zostało określone w pierwszej części konfiguracji. -
path = ~/wyszukiwanie/index/wiadomosci/idx
- definicja ścieżki w której zostaną zapisane wszystkie pliki stworzone przez indexera z dodanym prefixem idx.
Konfiguracja indexera z maksymalnym limitem na pamięć 128MB:
indexer { mem_limit = 128M }
Uruchamianie indeksowania
Poniższa komenda uruchomi indeksowanie
indexer --config ~/wyszukiwanie/conf/sphinx.conf --verbose wiadomosci
Co każde 1000 zindeksowanych dokumentów indexer wypisze powiadomienie. Po zakończeniu indeksowania zostoną wyświetlone jego statystyki.
Wyszukiwanie
Za wyszukiwanie odpowiada daemon searcgd
. Poniżej znajduje się przykład konfiguracji oraz sposób jego uruchomienia.
Konfiguracja
Konfiguracja tak jak we wcześniejszych częsciach znajduje się w pliku ~/wyszukiwanie/conf/sphinx.conf
:
searchd { listen = /home/''login''/wyszukiwanie/searchd.sock log = /home/''login''/wyszukiwanie/log/searchd.log query_log = /home/''login''/wyszukiwanie/log/query.log read_timeout = 5 client_timeout = 300 max_children = 30 pid_file = /home/''login''/wyszukiwanie/log/searchd.pid max_matches = 1000 seamless_rotate = 1 preopen_indexes = 1 unlink_old = 1 mva_updates_pool = 1M max_packet_size = 8M max_filters = 256 max_filter_values = 4096 max_batch_queries = 32 workers = 4 dist_threads = 4 }
Większość z opcji jest ustawiona standardowo i nie wymaga zrozumienia.
Uruchamianie daemona
Aby uruchomić daemon searchd
należy skorzystać z polecenia:
searchd -c ~/wyszukiwanie/conf/sphinx.conf
Wyszukiwanie za pomocą PHP
Sphinx search ma bardzo dużo klientów, jednym z nich jest PHP API. Poniżej znajduje się przykład:
<?php header('Content-Type: text/plain; charset=iso-8859-1'); include('sphinxapi.php'); $cl = new SphinxClient(); $cl->SetServer("/home/''login''/wyszukiwanie/searchd.sock"); $cl->SetSortMode(SPH_SORT_RELEVANCE); $results = (int)$_GET['results']; $offset = (int)$_GET['offset']; $cl->SetLimits($offset, $results); $min_date = (int)$_GET['mindate']; $max_date = (int)$_GET['maxdate']; $cl->SetFilterRange('date', $min_date, $max_date); if ($_GET['mode'] == 'All') { $cl->SetMatchMode(SPH_MATCH_ALL); } else if ($_GET['mode'] == 'Any') { $cl->SetMatchMode(SPH_MATCH_ANY); } else if ($_GET['mode'] == 'Phrase') { $cl->SetMatchMode(SPH_MATCH_PHRASE); } else if ($_GET['mode'] == 'Extended') { $cl->SetMatchMode(SPH_MATCH_EXTENDED); } $keywords = preg_replace("/"/", "\"", $_GET['keywords']); $result = $cl->Query( $keywords, $_GET['index'] ); if ( $result === false ) { echo "ERROR|Query failed: " . $cl->GetLastError() . "\n"; } else { if ( $cl->GetLastWarning() ) { echo "WARNING|" . $cl->GetLastWarning() . "\n"; } if ( ! empty($result['matches']) ) { print_r($result['matches']); } } ?>
i przykładowe użycie za pomocą curl:
curl "http://localhost/search.php?keywords=Anna+Team&results=20&offset=0&mindate=20090101&maxdate=20140806&mode=Phrase&index=news"