Tipy pro Sphinx Search

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.
Seriál: Úvod do Sphinx Search (4 díly)
- Úvod do Sphinx Search 27. 5. 2013
- Konfigurace Sphinx Search 10. 6. 2013
- Sphinx Search API 24. 6. 2013
- Tipy pro Sphinx Search 8. 7. 2013
Nálepky:
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:
- 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. - 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 automatikuexpand_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:
- 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.
- 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.
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
Jinou utilitu bych nehledal. Zádrhel je v tom, že pokud pomocí charset_table oříznete diakritiku, skutečně tam pak vznikne mnoho duplicitních výrazů. Např. „Abcházií“ i „Abcházii“ se převede na „abchazii“.
Stačí výsledný soubor prohnat nějakou utilitou na odstranění duplicitních řádků a je po problému. Např.:
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.
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
sphinxsearch-wordforms.tar.gz