Přejít k navigační liště

Zdroják » Databáze » Tipy pro Sphinx Search

Tipy pro Sphinx Search

Články Databáze

V závěrečném dílu seriálu o Sphinx Search vám ukážu několik tipů a doporučení, které se do seriálu nevešly a kterými bych vás chtěl nasměrovat při řešení konkrétních problémů, na které můžete narazit.

Multi-queries

Pokud potřebujete Sphinxu položit více dotazů, je dobré využít tzv. multi-queries, tedy možnost poslat dotazy najednou a rovněž najednou získat jejich výsledky hledání. To zvyšuje výkon dvěma způsoby:

  1. Snížení režie – každý dotaz s sebou nese určitou režii v komunikaci se searchd. Položením dotazů najednou tuto režii minimalizujete.
  2. Optimalizace dotazů – Sphinx nejprve analyzuje, co mají dotazy společného, a tyto věci vyhodnotí pouze jednou. Optimalizaci dělá na dvou úrovních: query optimization (společně vyhodnotí dotazy, které jsou stejné, a liší se jen filtrováním/tříděním) a subtree optimization (u rozdílných dotazů hledá, zda nelze vyhodnotit společně alespoň jejich části).

Použití je jednoduché. Místo přímého volání metody Query(), budete dotazy pouze přidávat pomocí AddQuery() a nakonec je pošlete najednou pomocí RunQueries(). Mezi přidáním jednotlivých dotazů můžete samozřejmě přenastavit filtry, třídění, váhy apod.

Faceted navigace

Poslední dobou se v souvislosti s vyhledáváním hodně mluví o tvz. Faceted search. V kostce: Uživatel položí dotaz a kromě výsledků hledání se mu, obvykle na levé straně, zobrazí řada filtrů, kterými může svůj dotaz dále upřesnit. Důležitou vlastností faceted navigace je, že ve filtrech nabízí jen ty hodnoty, které se vyskytují v daném výsledku hledání.

Nejde tedy ani tak o vlastnost vyhledávací technologie, jako spíš o UX prvek. Prostě ustálený způsob, jak nabídnout uživateli možnost filtrování. Myslím, že z toho důvodu v dokumentaci Sphinx Search o facetech nic nenajdete, čímž vzniká mylný názor, že Sphinx facety nepodporuje.

Na jednu stranu je to pravda, na druhou na těch facetech vůbec nic není a udělat je ve Sphinxu není nic těžkého. Co vlastně potřebujeme? Kromě výsledků hledání potřebujeme pro každý filtr, který chceme ve facetech nabídnout, položit další dotaz Sphinxu. Tento dotaz bude úplně stejný, jen mu pomocí SetSelect() nastavíme seskupování (GROUP BY) právě podle tohoto pole/kriteria. Tím získáme hodnoty, které v rámci tohoto filtru máme uživateli nabídnout a případně i počet nalezených položek v rámci každé hodnoty.

Facet filtrů máme obvykle více, takže celkový počet dotazů bude počet_facet_filtrů + 1. A asi už tušíte kam mířím: Nabízí se tyto dotazy položit najednou pomocí výše zmíněných multi-queries.

Pokud vám to přijde komplikované a nebo máte těch filtrů tolik, že je toto řešení příliš low-level, doporučuji použít knihovny třetích stran: fSphinx pro Python, fSphinxPhp pro PHP nebo Thinking Sphinx pro Ruby. Ty vám umožní nadefinovat facet filtry všeho druhu a ty multi-query to sestavuje a zpracovává za vás.

Našeptávač

Sphinx Search se svou rychlostí přímo nabízí k využití jako zdroj dat pro našeptávač. Doby, kdy se našeptávalo jen zleva, jsou pryč. Dnes se očekává, že našeptávač bude hledat i uprostřed textu a tedy potřebujete našeptávat fulltextově. Pokud uživatel napíše třeba sp se, do Sphinxu by měl jít dotaz sp* se* a našeptávač by měl nalézt položku Sphinx Search.

  • Používejte automatickou expanzi slov. Abyste to rozšíření hvězdičkou nemuseli přidávat k uživatelskému dotazu sami, vypněte v konfiguraci indexu volbu enable_star = 0 a místo ní zapněte automatiku expand_keywords = 1. Ta za vás ty hvězdičky doplní a vy můžete dotaz Sphinxu poslat bez dalších úprav tak, jak ho uživatel napsal.
  • Pozn.: Expanze je ve skutečnosti komplexnější. Nepřidává pouze hvězdičku, ale každé slovo expanduje na (slovo | *slovo* | =slovo). Hledá tedy volnou shodu, expandované slovo nebo přesnou shodu.
  • Pro našeptávač doporučuji vytvořit samostatný index. Data, která budete našeptávat, nejsou obvykle shodná s daty, nad kterými vyhledáváte. Buď našeptáváte z nějakých statistik vyhledávání nebo chcete do našeptávání přidat třeba ještě kategorie apod. A v neposlední řadě budete chtít mít index jinak nakonfigurovaný.
  • Indexujte jen to, co potřebujete. Většinou stačí název položky a URL, na které odkazuje. Index tak může být nepoměrně menší a tudíž i rychlejší, což v tomto případě potřebujeme.
  • Indexujte vše, co potřebujete. Na druhou stranu je největším zabijákem výkonu situace, kdy nemáte indexováno všechno, co potřebujete vracet. Snažte se vše udělat tak, abyste při našeptávání nic nemuseli dotahovat z databáze.
  • Nevíte-li, jak udělat našeptávač na straně klienta, doporučuji skvělé řešení Twitter Typeahead – neplést s tím jednoduchým Bootstrap-typeahead.

Čeština – věčný problém

Sphinx Search má technicky dva způsoby, jak řešit ohýbání slov:

  1. Stemmer – součástí Sphinx Search je stemmer pro angličtinu, ruštinu, češtinu a arabštinu. Nevím, jak ty ostatní, ale stemmer pro češtinu dává výsledky spíš horší, protože najde spoustu věcí, které najít nemá. Nedoporučuji.
  2. Slovníky – slovníky jsou technicky podporované dobře. Slovník pro Sphinx je obyčejný textový soubor, obsahující řádky slovní_tvar > slovo. V zásadě jen převádí různé tvary slov na základní tvar a to jak při indexaci, tak při vyhledávání.

Problém je, kde ty slovníky vzít. Z open-source světa se nabízí pouze slovníky Ispell, Aspell, MySpell a Hunspell. Tyto slovníky lze převést do požadovaného tvaru pomocí utility spelldump, která je součástí Sphinx Search.

Pro vybraný jazyk potřebujete vždy dva soubory *.dict a *.aff. Pokud si slovníky nainstalujete z linuxové distribuce, tyto zdrojové soubory tam pravděpodobně nenajdete. Je potřeba je získat přímo od zdroje, například Česká data pro ispell nebo hunspell_dictionaries.

Výsledky jsou o dost lepší než v případě stemmeru, ale na nějaké problémy určitě narazíte. Pak záleží na konkrétních datech, jestli se nevyplatí vzít open-source slovník jen jako základ a ten přepisovat vlastním slovníkem nějakých výjimek, které budou řešit anomálie nebo speciální požadavky.

Tip: Pomocí slovníků můžete stejným způsobem řešit i synonyma:  synonymum > slovo.

Zvýrazňování slov ve výsledcích hledání

Určitě to znáte z Googlu: Zadáte dotaz a v nalezených výsledcích jsou hledaná slova zvýrazněna. Sphinx má k tomu jednoduchou metodu BuildExcerpts($docs, $index, $words, $opts=array())

$docs je pole stringů, které chcete obarvit, $index je jméno použitého indexu a $words jsou slova pro zvýraznění. Volitelně můžete přidat mnoho různých nastavení přes $opts.

Tip: Tím, že se $words zadávají samostatně, je možné zvýrazňovat třeba i trochu něco jiného, než se ve skutečnosti vyhledávalo.

Pokud používáte hvězdičkové rozšíření, fráze, proximitní operátory, stemmer nebo slovníky, budou se samozřejmě zvýrazňovat všechny nalezené tvary.

Závěr

Co dál? Pokud vás Sphinx zaujal, doporučím na závěr ještě několik zdrojů:

  • Používejte referenční příručku – je téměř vyčerpávající a velmi přehledná.
  • Sledujte Sphinx Blog – několikrát za měsíc tam vyjde článek, vysvětlující nějakou konkrétní problematiku.
  • Pokud toužíte po hlubším poznání, přečtěte si knihu Introduction to Search with Sphinx. Autorem je Andrew Aksyonoff, tedy přímo tvůrce Sphinx Search.

Komentáře

Subscribe
Upozornit na
guest
5 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
michal

Ahoj,

používám slovník a Sphinx mi téměř na každý řádek zahlásí duplicitu, např. WARNING: index ‚test1‘: duplicate wordform found ( ‚Abcházií > Abcházie‘ ). Fix your wordforms file ‚/var/lib/sphinx/data/wordforms.txt‘. Vyhledávání je funkční, nicméně warningy dělají zmatek v logu a má to negativní vliv na výkon.

Wordform.txt jsem získal konverzí českého Ispell slovníku (UTF-8) z https://issues.apache.org/jira/browse/LUCENE-4311.

spelldump –c /etc/sphinx/sphinx.conf cs_CZ.dic cz_CZ.aff wordforms.txt

charset_table = 0..9, A..Z->a..z, _, a..z, U+0e1->a, U+0c1->a, U+10d->c, U+10c->c, U+10f->d, U+10e->d, U+0e9->e, U+0c9->e, U+11b->e, U+11a->e, U+0ed->i, U+0cd->i, U+148->n, U+147->n, U+0f3->o, U+0d3->o, U+159->r, U+158->r, U+161->s, U+160->s, U+165->t, U+164->t, U+0fa->u, U+0da->u, U+16f->u, U+16e->u, U+0fd->y, U+0dd->y, U+17e->z, U+17d->z,

Výsledný soubor má 90MB.

Má někdo podobný problém? Existuje lepší postup jak dostat český slovník pro sphinx? Znáte nějakou utilitu na konverzi slovníku synonym z Ispell balíku? Díky

michal

Problém je dvojí
– generují se záznamy typu slovo > slovo, tj. co je na levé straně je i na pravé
– vznikají cyklické závislosti

Normalizace pomocí uniq tyto problémy neřeší.

Našel jsem dost diskuzí, ale žádné out-of-the-box řešení. Zajímalo by mě jak vypadá funkční český slovník a z jakého zdroje byl generovaný.

Samostatná otázka je jak využít Ispell slovník synonym, tj. např z openoffice th_cs_CZ_v3.dat.

radek

dospeli jste k nejakemu vysledku ? docela by me to zajimalo, v soucasne chvili experimentuji s elasticsearchem, ale ten ma v podstate stejny problem a sphinx uz mam v produkci nasazeny, jen bez ceskeho „ohybani“, takze pokud by se to podarilo dostat primo do sphinxu, tak bych byl radsi.
dekuji

Petr

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.