Logo

Oracle Text - vyhledávejte na úrovni

Vložil Pavel Klobasa, 7. Únor 2010 - 22:35

Internetové obchody musí mít košík, redakční systémy autory a články, webové prezentace nápaditou grafiku… ale je jedna vlastnost, kterou by měly mít všechny internetové aplikace a která bývá u webových aplikací často odbytá – fulltextové vyhledávání. Přitom jde o důležitou vlastnost, webové aplikace by měly počítat s nepoučeným uživatelem, který na stránky přijde poprvé, nevyzná se v nich a něco hledá – a právě zde by mělo nastoupit fulltextové vyhledávání.

Než se dostaneme k technologii Oracle Text, pojďme si projít alternativy…

Ideální fulltext by měl mít… aneb požadavky

Co vlastně od fulltextu požadujeme? Zdánlivě to vypadá jednoduše – najít všechny výskyty zadaného slova. Realita je složitější, fulltextový engine by měl umět:

  1. podpora logických operátorů AND, OR a NOT a podpora vyhledávání víceslovných frází
  2. při vyhledávání nebrat ohled na diakritiku
  3. výsledky řadit podle relevance
  4. vyhledávat v různých typech dokumentů bez rozdílu (tj. prohledávat produkty, články, výrobce, diskuzní příspěvky, popisy obrázků…)
  5. nález v názvu má vyšší váhu než nález v obsahu
  6. brát v úvahu kořeny slov, synonyma či podobná slova
  7. prohledávat jen viditelné dokumenty, tj. jen prodejné produkty nebo publikované články

Uznejte, že tyto požadavky jsou přirozené, uživatel něco takového očekává. Bohužel často marně…

Řešení pomocí like

Řešení fulltextu v internetové aplikaci často dopadá tak, že se v kódu objeví SQL dotaz podobný následujícímu:

select * from produkty where popis like '%počítač%'

Přemýšlivější programátor k tomu doplní AND a OR, odstraní HTML v popisech, zvítězí nad diakritikou a efektivně prohledá i různé typy záznamů. Přesto je relevance vypočítaná podle počtu výskytů nedosažitelná…

Ale je tu ještě jeden problém – efektivita vyhledávání. Protože prohledávané políčko není indexované (a většina databází ani fulltextový index neumí), tak vyhledávání probíhá procházením celé tabulky, a je tedy zoufale neefektivní. Pro malé weby to problém není, pro větší to již může být „smrtelné“. Takový like vám dokáže žhavit nejenom procesor, jak píše Pavel Stěhule, ale „překvapivě“ i disk a diskové cache.

Google a Lucene

Máte-li problém, pomůže pan Google – ano, proč nevyužít cizí internetovou službu, která je navíc zdarma? Říká se jí Google Custom Search API. Stačí její vyhledávání omezit na váš web. Zde bych viděl největší háček v aktualizaci dat. Nejprve po zveřejnění nového dokumentu bude chvíli trvat, než ho Google zaindexuje a naopak po stažení dokumentu bude chvíli trvat, než se dokument přestane objevovat ve výsledcích. A věřte, že pokud potřebujete na e-shopu prodávat nějakou horkou novinku, tak ta chvíle je zatraceně dlouhá…

Jiným řešení je použití fulltextové knihovny, v případě Javy například oblíbenou Apache Lucene. Základní problémy této knihovny, jako třeba synchronizaci souborového indexu s databází, řeší obalovací knihovna Hibernate Search, ale jeden problém zůstává – jak spojit výsledky vyhledávání z Lucene s omezením na data, která mají spíše databázový charakter – to je výše zmiňovaný problém s omezení viditelnosti (nevydané články, historické produkty atp). Nebo jak rozumným způsobem seřadit výsledky fulltextu podle položky v databázi, například podle ceny.

Oracle Text

Po delším úvodu se konečně dostáváme k technologii z titulku. Oracle Text splňuje (nebo může splnit při vhodném použití) všech sedm výše uvedených požadavků s vyjímkou bodu 6. Oracle Text plně nepodporuje češtinu (tj. ohýbání slov, synonyma atp.) (Pravda, našel jsem na internetu zásuvný modul pro češtinu v ceně několika desítek tisíc korun na procesor, ale to je pro internetové aplikace cena mimo dosažitelnou realitu. Nebudu to tedy více rozebírat.)

Existuje několik způsobů jak Oracle Text používat, nejnázornější se mi jeví použití XML, které vám i v následujících odstavcích předvedu. Omlouvám se předem, ale Oracle Text je poměrně rozsáhlá knihovna, a proto můj výklad musí být zjednodušený.

Vytvoření indexu

Nejprve je vhodné vytvořit tabulku do které budeme ukládat XML obraz původních dat:

CREATE TABLE doc(
  uuid CHAR(32) NOT NULL,
  xmldata CLOB NOT NULL,
  PRIMARY KEY uuid
)

Po té musíme vymyslet nějaký vhodný XML formát, který vhodně reprezentuje indexovaná data, pro jednoduchost volím následující:

<product>
  <title>Intel 386</title>
  <content>Rychlý procesor známého výrobce Intel
      s možností připojení matematického koprocesoru</content>
</product>

Do tabulky doc jsme zapsali všechny produktové záznamy, následuje vytvoření fulltextového indexu nad políčkem xmldata:

CREATE INDEX doc_fulltext_idx ON doc(xmldata)
  INDEXTYPE IS CTXSYS.CONTEXT
  PARAMETERS ('section group CTXSYS.PATH_SECTION_GROUP');

Příklady dotazů

A nyní již můžeme vyhledávat. Dotazy se zadávají pomocí funkce contains, v níž mohou být uvedeny různé operátory pro knihovnu Oracle Text:

SELECT uuid FROM doc
  WHERE contains(xmldata,'procesor and (intel not amd)',1) >0

Oracle Text dokáže vypočítat i relevanci a výsledky podle ní seřadit. Zde pomůže kouzelné slůvko score a magická konstanta přidaná jako poslední parametr funkce contains:

SELECT score(1),uuid FROM doc
  WHERE contains(xmldata,'procesor',1)>0
  ORDER BY score(1) desc

Někdy se hodí vyhledávat jen v části dokumentu, protože Oracle Text podporuje dotazování ve stylu XPath, je takový dotaz jednoduchý:

SELECT uuid FROM doc
  WHERE contains(xmldata, 'procesor INPATH (/product/title)') > 0;

Na počátku jsem sliboval přidělit větší váhu výskytu v nadpisu než v obsahu. Myslím, že následující dotaz je názorný:

SELECT score(1), uuid FROM doc
  WHERE contains(xmldata,
  'DEFINESCORE(procesor,5*OCCURRENCE) INPATH (/product/title) accum
  DEFINESCORE(procesor,OCCURRENCE) INPATH (/product/content)',1) > 0
  ORDER BY score(1) desc

Další možnosti

Výše uvedené příklady jsou jen stručným úvodem, Oracle Text toho umí mnohem více. Například funkce NEAR bere v úvahu při výpočtu relevance vzdálenost mezi dvěma hledanými slovy. Funkce FUZZY podporuje „nepřesné“ vyhledávání, v češtině ho můžeme použít pro ignorování překlepů. Oracle Text podporuje i znak % v stylu našeho dobře známého LIKE, ale funguje mnohem efektivněji, neboť je možné indexovat data podle fragmentů slov.

Na vyhledávání pochopitelně nemusíte používat plnou sílu XML, Oracle Text umí indexovat i přímo hlavní datové tabulky. Takhle byl ale můj text názornější, a kromě toho není právě tohle hezká ukázka XML databáze?

Závěr

Umí vaše internetová aplikace „opravdový“ fulltext a jak ho řešíte vy?

© 2005-2008 oXy Online s.r.o., všechna práva vyhrazena.