Sphinx Search API

Dnes si ukážeme, jak pokládat Sphinxu dotazy z vlastní aplikace pomocí Sphinx API, jaké jsou možnosti vyhledávání, jak výsledky filtrovat, třidit… Součástí Sphinx Search je API pro PHP, Perl, Python, Ruby a Javu. Já to ukážu na příkladu PHP.

Seriál: Úvod do Sphinx Search (4 díly)

  1. Úvod do Sphinx Search 27.5.2013
  2. Konfigurace Sphinx Search 10.6.2013
  3. Sphinx Search API 24.6.2013
  4. Tipy pro Sphinx Search 8.7.2013

 

Nejjednodušší příklad

Použijeme-li nastavení z minulého článku o konfiguraci Sphinx Search, úplně základní dotaz bychom v PHP položili takto:

<?php
$sphinx = new SphinxClient();
$sphinx->SetServer('localhost', 9312);
$result = $sphinx->Query('dotaz', 'myindex', 'Komentář do logu');
print_r($result);

Pokud se navíc připojujete na defaultní localhost:9312, není nutné volat ani SetServer(). Výsledkem hledání je pak asociativní pole, jehož strukturu nejlépe pochopíte, když si ji zobrazíte pomocí print_r(). Obsahuje nalezené položky matches a několik dalších údajů o zpracování dotazu.

Všiměte si, že neexistuje žádný SetIndex($index). Název indexu, nebo indexů, které chceme prohledávat, se předává s každým dotazem. Pokud parametr vynecháte nebo nastavíte na *, budou se prohledávat všechny indexy.

Hledání přes více indexů

Pokud zadáte více indexů, např. 'index1, index2', jejich pořadí je důležité. Může se stát, že se v obou najde dokument se stejným ID. Potom se vždy bere údaj z později uvedeného indexu. Toho se využívá, když používáte pro aktualizaci tzv. delta index. Pak byste zadali něco jako 'main, delta'. Výsledky z menšího delta indexu aktualizovaného třeba každých 10 minut přepíší výsledky z většího hlavního indexu, který se celý přeindexuje třeba jednou za den.

Komentář do logu

K dotazu lze dále přidat komentář do logu. Pokud máte nastaven query_log (minule jsme nastavovali), tak se tento komentář uloží spolu s dotazem. Toho lze využít například při zpracování statistik toho, co uživatelé hledají. Abyste rozlišili, dotazy uživatele od nějakých pomocných dotazů, co vaše aplikace pokládá, je šikovné si k nim přidat nějakou značku, např. #user.

Další možnosti vyhledávání

Než zavoláte $sphinx->Query() můžete nastavit řadu možností, jak výsledky hledání ovlivnit. Kromě fulltextového hledání můžete hledat parametricky (filtrování), nastavit způsob porovnávání SetMatchMode(), vybrat atributy, které chcete vracet SetSelect(), nastavit váhy jendotlivých polí SetFieldWeights() nebo nastavit řazení výsledků SetSortMode().

Komplexnější dotaz by mohl vypadat takto:

<?php
$sphinx = new SphinxClient();
$sphinx->SetServer('localhost', 9312);
$sphinx->SetMatchMode(SPH_MATCH_EXTENDED);
$sphinx->SetSortMode(SPH_SORT_TIME_SEGMENTS, 'datetime');
$sphinx->SetFieldWeights(array(
    'title' => 10,
    'description' => 5,
));
$sphinx->SetLimits(0, 100);

$result = $sphinx->Query('dotaz', 'myindex', 'Komentář do logu');
print_r($result);

Match mode (fulltextové dotazy)

Fulltextový dotaz zadáváme jako první parametr Query('dotaz'). Možnosti dotazu a způsob porovnávání je dán nastavením match modu SetMatchMode(). Z toho plynou i operátory, které se dají v dotazu použít. Sphinx má 6 match módů:

  • SPH_MATCH_ALL – všechna slova (default)
  • SPH_MATCH_ANY – libovolné slovo
  • SPH_MATCH_PHRASE – jako kdyby byl dotaz v uvozovkách
  • SPH_MATCH_BOOLEAN – přidává operátory AND, OR, NOT a závorky ()
  • SPH_MATCH_EXTENDED – Extended query syntax (preferovaný mód)
  • SPH_MATCH_FULLSCAN – pokud nechcete hledat fulltextově, ale jen parametricky

SPH_MATCH_EXTENDED je preferovaný mód. Umožňuje vše, co kterýkoliv jiný mód a jeho “Extended query syntax” je interním dotazovacím jazykem Sphinx Search. Dotaz v jakémkoliv jiném módu, je stejně převeden na SPH_MATCH_EXTENDED, takže většinou není důvod používat jakýkoliv jiný mód. A pokud je fulltextový dotaz prázdný string, vždy se automaticky aktivuje mód SPH_MATCH_FULLSCAN.

Pozn.: Zkratka použitého match modu (all, any, phr, bool, ext, scan) se rovněž objeví v query logu.

Fulltextové operátory

V SPH_MATCH_EXTENDED mód přidává mnoho užitečných operátorů. Default operátor je AND. Dotazy slovo slovo a slovo & slovo jsou tedy shodné.

Kromě operátoru & můžete dále používat OR slovo | slovo, zakazovat slova -slovo, !slovo, pomocí kulatých závorek libovolně vytvářet poddotazy slovo -(slovo | slovo).

Můžete používat hvězdičkové rozšíření slovo*, pomocí uvozovek vytvářet fráze "slovo slovo", a i v uvozovkách lze použít hvězdičky "slovo* slovo".

Vyhledávání lze omezit na vybraná pole takto:
@title slovo -@description slovo @(title,description) (slovo | slovo).

Operátory << >> nám umožní vynutit pořadí slov slovo << před << slovem. Fráze v uvozovkách lze rozšířit proximitním operátorem, který nám umožní říct, že mezi slovy může být ještě uvedený počet jiných slov, např. dvě: "slovo slovo"~2 . Quorum operátor zase říká, že stačí, když z uvedených slov bude odpovídat uvedený počet, tady nám například stačí 2 shody ze tří slov: "slovo slovo slovo"/2.

Od verze 2.0.1 ještě přibyly operátory SENTENCE a PARAGRAPH, které požadují, aby daná slova byla ve stejné větě, resp. odstavci. A dále přibyl operátor slovo NEAR/2 slovo definující maximální vzdálenost slov.

Třídění

Sphinx má několik způsobů třídění výsledků hledání. Všechny mají své využití.

  • SPH_SORT_RELEVANCE – třídění podle relevance
  • SPH_SORT_ATTR_DESC (resp. SPH_SORT_ATTR_ASC) – třídění podle atributu
  • SPH_SORT_TIME_SEGMENTS – třídění podle časových segmentů
  • SPH_SORT_EXTENDED – rozšířená definice třídění (podobná SQL)
  • SPH_SORT_EXPR – třídění definované matematickým výrazem

Výpočet relevance

Pro výpočet relevance můžete poměrem čísel nastavit, jakou váhu budou mít jednotlivá fulltextově indexovaná pole. To uděláte například takto, tak bude mít titulek dvojnásobnou váhu než popis.

<?php
$sphinx->SetFieldWeights(array(
    'title' => 10,
    'description' => 5,
));

V extended módu lze pomocí metody SetRankingMode() navíc určit, jaký algoritmus se použije, ale to už je pokročilejší věc, kterou většinou nevyužijete.

Extended sort

Podobně jako u match modu platí, že SPH_SORT_EXTENDED umí kombinovat ostatní mody, ale kromě časových segmentů SPH_SORT_TIME_SEGMENTS a kromě SPH_SORT_EXPR (tem má úplně jinou syntaxi). Následující dvojice nastavení jsou ekvivalentní:

// Trideni podle data
$sphinx->SetSortMode(SPH_SORT_ATTR_DESC, 'datetime');
$sphinx->SetSortMode(SPH_SORT_EXTENDED, 'datetime DESC');

// Trideni podle relevance
$sphinx->SetSortMode(SPH_SORT_RELEVANCE);
$sphinx->SetSortMode(SPH_SORT_EXTENDED, '@relevance DESC');

SPH_SORT_EXTENDED to ovšem umí zkombinovat:

// Trideni podle relevance a data
$sphinx->SetSortMode(SPH_SORT_EXTENDED, '@relevance DESC, datetime DESC');

Časové segmenty

Často se stane, že chcete mít výsledky seřazené podle data/času, ale zároveň trochu podle relevance. Tedy například nové články musí být nahoře, ale zároveň musí řazení zohledňovat relevanci vůči dotazu. A to právě umí SPH_SORT_TIME_SEGMENTS. Výsledky hledání jsou rozděleny na 6 časových segmentů v tomto pořadí: poslední hodina, den, týden, měsíc, 3 měsíce, vše starší. V rámci těchto segmentů jsou výsledky řazeny podle relevance.

Abecední třídění

Slabinou Sphinx Search je, že nemá abecední třídění. Módy SPH_SORT_ATTR_DESC / SPH_SORT_ATTR_ASC lze použít jen pro čísla, datum, bool…

Částečným řešením je nadefinovat atribut se zvláštní datovým typem string ordinal sql_attr_str2ordinal = jmenosloupce. Takový string se převede na velké číslo, podle kterého již třídit lze. Neindexuje se ale ani pro fulltextové vyhledávání, ani původní string není vracen. Zatím je to ale, bohužel,  nedotažené, protože při indexování není zohledněno, jakým jazykem je text psán (takže známý problém se zařazením našeho ch).

Jelikož požadavek na abecední třídění není moc častý, asi ani není prioritou to doladit.

Parametrické hledání (filtrování)

Vyhledávání podle atributů, tedy filtrování, lze nastavit pomocí několika metod:

SetFilter() umožňuje pro zadaný atribut zadat pole povolených nebo naopak zakázaných hodnot.

SetFilterRange() je podobná, ale nezadáváme výčet hodnot, ale jejich rozsah. Pak jsou tam ještě filtry pro float čísla SetFilterFloatRange() a geo lokace SetGeoAnchor().

Filtrovací metody můžete zavolat opakovaně. Potom musí položky projít postupně všemi filtry.

 Závěr

Příští, závěrečný, díl seriálu o Sphinx Search bude takový přehled praktických tipů, jak nejlépe řešit konkrétní situace, na které jsem v praxi narazil.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 1

Přehled komentářů

tomas.volsansky Sphinx
Zdroj: https://www.zdrojak.cz/?p=9036