منبع اصلی نوشتار زیر در این لینک قرار دارد

معرفی و آموزش پیاده‌سازی Apache Lucene

سلام،

حدود یک سال و نیم قبل در مطلبی به معرفی خزنده‌های وب (Web crawlers) و آموزش راه اندازی یک خزنده وب ساده به زبان جاوا پرداختم. در طول این مدت افراد بسیاری در مورد خزنده‌های وب با من تماس گرفتند و سوالات مختلفی در مورد این خزنده‌ها داشتند. در این مطلب به معرفی و آموزش Apache Lucene که به منظور جستجو فایل‌های متین استفاده می شود، می پردازم. همچنین در آینده به بررسی ۳ محصول Hadoop, Apache Solr و Apache Nutch خواهم پرداخت.

Apache Lucene

آپاچی لوسن کتابخانه ای برای راه اندازی موتورهای جستجوی متن می باشد. این کتابخانه آزاد بوده و تحت لایسنس Apache Licene 2.0 منتشر می شود. این کتابخانه به زبان جاوا (Java) نوشته شده و سپس به زبان های Delphi, Perl, C#, C++, Python, Ruby, و PHP پیاده سازی (پورت) شده است.
این کتابخانه این امکان را برای شما فراهم می آورد تا هر نوع موتور جستجوی متنی مانند موتور جستوی وب، لوکال (محلی) ویا فقط ویژه یک وب سایت را ایجاد نمایید. در نظر داشته باشید که Apache Lucene فقط برای جستجو استفاده می‌شود و برای جمع‌آوری اطلاعات و تحلیل آن‌ها نیاز به ابزارهای دیگری مانند Solr و Nutch دارید.
برای دریافت این کتابخانه به صفحه دانلود آپاچی لوسن مراجعه نمایید. همچنین می توانید نسخه فعلی (۳.۶.۰) را از آدرس زیر دریافت نمایید:
دانلود کتابخانه آپاچی لوسن نسخه ۳.۶.۰

استفاده از کتابخانه Apache Lucene

در ادامه مراحل مختلف برای آماده‌سازی و انجام جستجو را بررسی کرده و در انتها سورس کامل این کلاس را مشاهده خواهید کرد.

مرحله اول: ایندکس کردن اطلاعات

قبل از هر چیز شما باید اطلاعاتی را که قصد جستجو در آن‌ها را دارید ایندکس نمایید. ایندکس کردن اطلاعات فواید زیادی دارد که یکی از مهم‌ترین آن‌ها مرتب‌سازی و افزایش سرعت جستجو است.
ایندکس اطلاعات در لوسن توسط دو کلاس Document و Field صورت می پذیرد. Document سند شما و Field اطلاعات مرتبط با سند مانند عنوان، محتوا و… است. این وظیفه شماست که اطلاعات خود از جمله رشته‌ها، انواع فایل‌ها، اطلاعات ذخیره شده در پایگاه داده و… را به کلاس Document تبدیل و ایندکس نمایید. در زیر تعامل Index, Document و Field را مشاهده می کنید:

 Index 
Document 1

Field A (name/value)

Field B (name/value)
Document 2

Field A (name/value)

Field B (name/value)

بعد از آماده سازی Document باید توسط کلاس IndexWriter، ایندکس را ذخیره می کنیم. پارامتر اول در فراخوانی IndexWriter دایکتوری ذخیره‌سازی ایندکس را مشاهده می‌کند.
با کدهای زیر چند عبارت را در حافظه دسترسی تصادفی (RAM) ذخیره کردیم:

Directory index = new RAMDirectory();
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, analyzer);

IndexWriter w = new IndexWriter(index, config);
addDoc(w, "Lucene in Action");
addDoc(w, "Lucene for Dummies");
addDoc(w, "Managing Gigabytes");
addDoc(w, "The Art of Computer Science");
w.close();

متد addDoc رشته‌ها را به ایندکس اضافه می کند:

private static void addDoc(IndexWriter w, String value) throws IOException {
    Document doc = new Document();
    doc.add(new Field("title", value, Field.Store.YES, Field.Index.ANALYZED));
    w.addDocument(doc);
  }
}

مرحله دوم: ایجاد کوئری (Query)

در این برنامه ما عبارت مورد نظر برای جستجو را از ورودی (stdin) دریافت می‌کنیم:

String querystr = args.length > 0 ? args[0] : "lucene";
Query q = new QueryParser(Version.LUCENE_36, "title", analyzer).parse(querystr);

مرحله سوم: انجام جستجو

در این مرحله کوئری (جستار؟) ساخته شده را بر روی ایندکس جستجو می کنیم. همچنین از کلاس TopScoreDocCollector برای بدست آوردن ۱۰ نتیجه مرتبط‌تر استفاده کرده ایم:

int hitsPerPage = 10;
IndexReader reader = IndexReader.open(index);
IndexSearcher searcher = new IndexSearcher(reader);
TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
searcher.search(q, collector);
ScoreDoc[] hits = collector.topDocs().scoreDocs;

مرحله چهارم: مشاهده نتایج

در انتها نتایج بدست آمده را نمایش می‌دهیم:

System.out.println("Found " + hits.length + " hits.");
for(int i=0;i<hits.length;++i) {
    int docId = hits[i].doc;
    Document d = searcher.doc(docId);
    System.out.println((i + 1) + ". " + d.get("title"));
}

همین!

کلاس HelloLucene

در زیر کلاس HelloLucene را یکجا مشاهده می فرمایید:

import java.io.IOException;

import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;

public class HelloLucene {
    public static void main(String[] args) throws IOException, ParseException {
        // 0. Specify the analyzer for tokenizing text.
        //    The same analyzer should be used for indexing and searching
        StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_36);

        // 1. create the index
        Directory index = new RAMDirectory();

        IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_36, analyzer);

        IndexWriter w = new IndexWriter(index, config);
        addDoc(w, "Lucene in Action");
        addDoc(w, "Lucene for Dummies");
        addDoc(w, "Managing Gigabytes");
        addDoc(w, "The Art of Computer Science");
        w.close();

        // 2. query
        String queryStr = args.length > 0 ? args[0] : "lucene";

        // the "title" arg specifies the default field to use
        // when no field is explicitly specified in the query.
        Query q = new QueryParser(Version.LUCENE_35, "title", analyzer).parse(queryStr);

        // 3. search
        int hitsPerPage = 10;
        IndexReader reader = IndexReader.open(index);
        IndexSearcher searcher = new IndexSearcher(reader);
        TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
        searcher.search(q, collector);
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        // 4. display results
        System.out.println("Found " + hits.length + " hits.");
        for (int i = 0; i < hits.length; ++i) {
            int docId = hits[i].doc;
            Document d = searcher.doc(docId);
            System.out.println((i + 1) + ". " + d.get("title"));
        }

        // searcher can only be closed when there
        // is no need to access the documents any more.
        searcher.close();
    }

    private static void addDoc(IndexWriter w, String value) throws IOException {
        Document doc = new Document();
        doc.add(new Field("title", value, Field.Store.YES, Field.Index.ANALYZED));
        w.addDocument(doc);
    }
}

منابع

شاد و پیروز باشید :)



برچسب ها : , , , , , ,