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

Zdroják » Databáze » Fulltext vyhľadávanie v CouchDB

Fulltext vyhľadávanie v CouchDB

Články Databáze

O CouchDB bolo už na Zdrojáku napísaných množstvo článkov. Od miniseriálu Jakuba Kulhana až po preklad kompletného sprievodcu CouchDB od Martina Malého. Dnes si ukážeme základné možnosti fulltextového vyhľadávania s nástrojom Lucene v tejto čoraz populárnejšej databáze.

Nálepky:

Na úvod krátke predstavenie, pre tých čo sa s CouchDB doteraz nestretli. CouchDB je dokumentovo orientovaná databáza s „iným“ prístupom k ukladaniu údajov. Umožňuje nám okrem iného vytvárať rôzne pohľady „views“ cez javascriptové map-reduce funkcie. Tieto funkcie nám úplne postačujú na vytvorenie napríklad stromovej štruktúry a jednoduchého zatrieďovania a získavania dát. Čo v prípade, že máme napríklad vlastný blog a chceme umožniť návštevníkom, aby mohli fulltextovo vyhľadávať v publikovaných článkoch? Riešení sa ponúka hneď niekoľko. S pomedzi mnohých môžme použiť napríklad Elasticsearch alebo Lucene.

Lucene

V tomto článku sa budeme venovať systému Lucene. Je to open source projekt zastrešený Apache Software Foundation. Kompletne napísaný v JAVE (na svoje fungovaniu vyžaduje nainštalované JRE) a je určený na fulltextové vyhľadávanie. Poskytuje možnosť škálovania a bez problémov spolupracuje s CouchDB. Je nenáročný na konfiguráciu, inštaláciu, a ako sa ochvíľu presvedčíme, aj na používanie.

Inštalácia Lucene

Jednoduchý návod na inštaláciu pre Ubuntu najdete tu.

Je v ňom však jeden preklep, a to v bode 11. Namiesto

apt-get install get-core maven2

použite

apt-get install git-core maven2

Pre ďaľšie distribúcie sú návody viac či menej rovnaké.

Configurácia CouchDB

Nakonfigurujeme rozhranie pre komunikáciu z couchdb-lucene  v CouchDB local.ini

Verzia CouchDB  < 1.1

[couchdb]
os_process_timeout=60000 ; // zvýšime čas pre vrátenie výsledku z CouchDB, je to dôležité ak nám vyhľadávanie trvá dlhšie

[external]
fti=/path/to/python /path/to/couchdb-lucene/tools/couchdb-external-hook.py // nastavíme cestu pre externé volanie lucene

[httpd_db_handlers]
_fti = {couch_httpd_external, handle_external_req, <<"fti">>} // zaregistrujeme http handler

Verzia CoucDB 1.1 +

Nová verzia  databázy už nepotrebuje toľko nastavovaní, úplne stačí iba registrácia http handlera z url na lucene.

[httpd_global_handlers]
_fti = {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:5985">>}

Pripravíme si testovacie dáta

Najskôr do databázy vložíme testovacie dáta, v ktorých chceme umožniť vyhľadávanie. Napríklad články z nášho blogu obsahujúce nadpis, perex a obsah. Príklad:

{
    "type": "article",
    "title": "Nadpis článku",
    "perex": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus nec.",
    "content": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas eu turpis metus, vel hendrerit ipsum. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla magna arcu, pharetra id gravida quis, fermentum convallis nisi. Nullam felis velit, rutrum nec aliquet et, viverra sed ante. Proin iaculis neque a enim interdum pharetra. Pellentesque eu euismod libero. Fusce tristique vehicula justo vel euismod. Vestibulum nec nisi sem, at faucibus quam. Aliquam quis ante metus."
}

Nastavenie indexovania

Vytvoríme si design dokument, v ktorom nastavíme parametre indexácie vyhľadávania. Každý dokument môže obsahovať neobmedzené množstvo indexov. Pre náš príklad si pripravíme dva. Prvý pre vyhľadávanie iba v nadpise článku, druhý pre vyhľadávanie vo všetkých položkách jednotlivých článkov.

{
    "_id":"_design/test",
    "fulltext":{
        "by_title":{
            "index":"function(doc){
                if(doc.type == 'article') // indexujeme len články
                  {
                     var ret = new Document();
                     ret.add(doc.title); // zaindexujeme položku title
                     return ret;
                  }
                  else
                  {
                     return null;
                  }
             }"
        },

        "by_article":{
            "index":"function(doc){
                if(doc.type == 'article') // indexujeme len články
                   {
                      var ret = new Document();
                      // pridáme všetky položky, v ktorých chceme vyhľadávať
                      ret.add(doc.title);
                      ret.add(doc.perex);
                      ret.add(doc.content);
                      return ret;
                    }
                    else
                    {
                      return null;
                    }
              }"
          }
    }
}

Vyhľadávanie

Môžeme sa pustiť do samotného vyhľadávania. Najprv skúsime vyhľadávať iba v nadpisoch.http://lo­calhost:5984/dbna­me/_fti/_desig­n/test/by_title?q=nad­pis

Odpoveďou na našu požiadavku je klasický JSON objekt, obsahujúci počet nájdených dokumentov, čas vyhľadávania a  zoznam „_ID“ nájdených dokumentov.

{
    "q": "nadpis",
    "skip": 0, // určuje koľko dokumentov bolo preskočených, url: &skip=
    "limit": 10, // url: &limit=
    "total_rows": 1,
    "fetch_duration", 1,
    "rows":[
        {
            "id":'article-1',
            "score": 1.82347
        }
     ]
}

Toto riešenie je nedostatočné; nakoľko na to, aby sme získali kompletný obsah vyhľadaných dokumentov, je nutné vykonať ďaľšiu GET požiadavku na samotný dokument. Pridaním parametra &include_docs do GETu docielime vrátenie okrem „_ID“ aj kompletného dokumentu uloženého v CouchDB. Výsledok:

"rows":[
        {
            "id":'article-1',
            "doc":
               {
                  "title":"Nadpis članku".....
                  // celý dokument
               }
            "score": 1.82347
         }
]

Tu však môže nastať ďaľšia situácia: ak by bol dokument (článok) veľký a my chceme zobrazovať iba určité dáta, napríklad do zoznamu vyhľadaných položiek alebo do suggestu, je zbytočné ťahať z DB celý dokument. Vrátime sa k indexom a jeden si upravíme

"by_title":{
    "index":"function(doc){
            if(doc.type == 'article') // indexujeme len články
               {
                   var ret = new Document();
                   ret.add(doc.title, {'field':'title', 'store':'yes'});
                   // zaindexujeme položku title a zároveň ju uložíme do lucene
                   return ret;
               }
               else
               {
                   return null;
               }
           }"
}

Požiadavku na vyhľadávanie upravíme: http://localhos­t:5984/dbname/_fti/_de­sign/test/by_ti­tle?q=title:nad­p*Vo výsledku dostaneme požadované dáta na zobrazenie nadpisov článkov bez prenosu celého dokumentu z DB.

Lucene poskytuje veľké množstvo nastavení a parametrov, ktoré je možné použiť pre indexáciu a získavanie dát. V tejto časti sme si ukázali základné možnosti fulltextového vyhľadávania pre CouchDB. Nabudúce si ukážeme vyhľadávanie v prílohách, či v našich zemepisných šírkach dôležitú možnosť vyhľadávať s diakritikou a bez nej.

Komentáře

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

Nad lucene existuje nastroj elasticsearch, ktery by stalo za to zminit jako alternativu:

http://www.elasticsearch.org/

michal.bartha

V clanku je to spomenute hned hore

„Riešení sa ponúka hneď niekoľko. S pomedzi mnohých môžme použiť napríklad Elasticsearch alebo Lucene.“

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.