Lucene入門,小例子,筆記

    最近在研究Lucene的用法,經過這兩天的努力,在網上搜索資料,還專門買了本書《開發自己的搜索引擎---Lucene+Heritrix》打算系統的學習一下這東西,大的項目是肯定離不開搜索引擎的,學吧,沒錯~ 這兩天有過無助、有過失落、也有過新發現時的欣喜若狂,總之最後還是做出了個小例子,怕以後再忘記,還是記錄一下吧~也記錄自己的成長,只有把學到的東西講給別人,纔算是真的會了,此例子也獻給那些正在搜索Lucene資料的朋友們吧~願對你們有所幫助~

    好了先貼代碼吧!

 

主類:TestIndex.java

 

package com.lj.test;

import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import net.paoding.analysis.analyzer.PaodingAnalyzer;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriter.MaxFieldLength;
import org.apache.lucene.queryParser.MultiFieldQueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.Filter;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleFragmenter;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;

import com.lj.entity.Product;
import com.lj.util.Configuration;

/**
 * Lucene初級小例子,簡單測試。
 * @author LiangJian
 * 2011-6-17 11:56:14
 */
public class TestIndex {
   
    /** 創建Lucene索引 */
    public void createIndex(String indexPath,List<Product> productList) throws Exception{
        //記錄開始時間
        long startTime = new Date().getTime();
        /** 建立索引,使用庖丁中文分詞器PaodingAnalyzer。*/
        IndexWriter indexWriter = new IndexWriter(indexPath, new PaodingAnalyzer(), true, MaxFieldLength.LIMITED);
        /**
         * 說明:
        * Field.TermVector.NO:不保存term vectors
          Field.TermVector.YES:保存term vectors
          Field.TermVector.WITH_POSITIONS:保存term vectors.(保存值和token位置信息)
          Field.TermVector.WITH_OFFSETS:保存term vectors.(保存值和Token的offset)
          Field.TermVector.WITH_POSITIONS_OFFSETS:保存term vectors.(保存值和token位置信息和Token的offset)
        */
        for(Product product:productList){
            Document doc = new Document();
            doc.add(new Field("p_id",product.getP_id()+"",Field.Store.YES,Field.Index.NO));
            doc.add(new Field("p_name",product.getP_name(),Field.Store.YES,Field.Index.ANALYZED));
            doc.add(new Field("p_price",product.getP_price(),Field.Store.YES,Field.Index.NO));
            doc.add(new Field("p_content",product.getP_content(),Field.Store.YES,Field.Index.ANALYZED));
            indexWriter.addDocument(doc);
        }
        // optimize()方法是對索引進行優化,進行了索引優化後,索引纔算是真正的生效。
        indexWriter.optimize();
        indexWriter.close();
        // 測試一下索引的時間
        long endTime = new Date().getTime();
        System.out.println("這花費了 " + (endTime - startTime)+ "毫秒來把數據增加到索引裏面去!");
    }
   
    /**
     * 按Content字段查詢
     * @param indexPath 索引文件路徑
     * @param keyword 關鍵字
     * @return
     * @throws Exception
     */
    public List<Product> searchByKeyWord(String indexPath,String keyword)throws Exception{
        List<Product> productList = new ArrayList<Product>();
        IndexSearcher search = new IndexSearcher(indexPath);
       
        long startTime = new Date().getTime();
       
        //下面的是進行p_content和p_name 範圍內進行搜索.
        String[] keywords = new String[]{"p_content","p_name"};//要檢索的字段
        /** 這裏需要注意的就是BooleanClause.Occur[]數組,它表示多個條件之間的關係,
         * BooleanClause.Occur.MUST表示and,
         * BooleanClause.Occur.MUST_NOT表示not,
         * BooleanClause.Occur.SHOULD表示or. 
         * */
        BooleanClause.Occur[] clauses = { BooleanClause.Occur.SHOULD,BooleanClause.Occur.SHOULD};//對應要檢索的字段的邏輯(與、或)
        Analyzer analyzer = new PaodingAnalyzer();//使用庖丁分詞,按分詞進行檢索
        //用MultiFieldQueryParser得到query對象
        Query query = MultiFieldQueryParser.parse(keyword, keywords, clauses, analyzer);//parser.parse(query);
        Filter filter = null;//過濾
        //開始匹配
        TopDocs topDocs = search.search(query, filter, 1000);
        System.out.println("共匹配到:"+topDocs.totalHits+"個.");
       
        for(ScoreDoc scorceDoc : topDocs.scoreDocs){
            Document doc = search.doc(scorceDoc.doc);
//            System.out.println(scorceDoc.doc+"---"+doc);//便於學習,可以打印出來看看。
            Product product = new Product();
            product.setP_id(Integer.parseInt(doc.get("p_id")));
            product.setP_name(doc.get("p_name"));
            product.setP_price(doc.get("p_price"));
//            product.setP_content(doc.get("p_content"));//不使用高亮
            product.setP_content(this.getHighLight(doc, analyzer, query, "p_content"));//使用高亮
            productList.add(product);
        }
        search.close();
        long endTime = new Date().getTime();
        System.out.println("檢索耗時: " + (endTime - startTime)+ "毫秒!");
        return productList;
    }
   
    /**
     * 高亮設置
     * @param doc
     * @param analyzer 分詞器
     * @param query
     * @param field 字段
     * @throws Exception
     * @reutrn 高亮後的值
     */
    public String getHighLight(Document doc,Analyzer analyzer,Query query,String field)throws Exception{
        //設置高亮顯示格式
//        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'><strong>", "</strong></font>");
        SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<b>", "</b>");
        /* 語法高亮顯示設置 */
        Highlighter highlighter = new Highlighter(simpleHTMLFormatter,new QueryScorer(query));
        highlighter.setTextFragmenter(new SimpleFragmenter(100));
        // 取 field 字段值,準備進行高亮
        String fieldValue = doc.get(field);
        TokenStream tokenStream = analyzer.tokenStream(field,new StringReader(fieldValue));
        //轉成高亮的值
        String highLightFieldValue = highlighter.getBestFragment(tokenStream, fieldValue);
        if(highLightFieldValue == null)
            highLightFieldValue = fieldValue;
        return highLightFieldValue;
    }

    /** 創建測試數據 */
    public List<Product> createProductList(){
        List<Product> productList = new ArrayList<Product>();
        for(int i=1;i<=20;i++){
            Product product = new Product();
            product.setP_id(i);
            product.setP_name("手錶"+i);
            product.setP_price((i*i+Math.random())+"元");
            product.setP_content("手錶的描述"+i+"塊");
            productList.add(product);
        }
        return productList;
    }

    /**
     * 測試主方法
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        TestIndex test = new TestIndex();
        String indexPath = Configuration.getInstance().read("config.properties", "indexPath");
        //創建Lucene索引
        test.createIndex(indexPath+"Product/index", test.createProductList());
       
        //從Lucene索引庫中——搜索
        List<Product> productList = test.searchByKeyWord(indexPath+"Product/index", "手錶4 描述3");
        //搜索結果
        for(Product product:productList){
            System.out.println("---------------");
            System.out.println("p_id:"+product.getP_id());
            System.out.println("p_name:"+product.getP_name());
            System.out.println("p_price:"+product.getP_price());
            System.out.println("p_content:"+product.getP_content());
            System.out.println("---------------");
        }
       
    }

}

 

讀取配置文件類:Configuration.java

package com.lj.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;

public class Configuration {
   
    //採用單例模式
    private static final Configuration configuration = new Configuration();

    private Configuration(){}
   
    public synchronized static Configuration getInstance(){
        return configuration;
    }
   
    public String read(String properties,String key){
        //讀取配置文件
        InputStream in = this.getClass().getClassLoader().getResourceAsStream(properties);
        Properties p = new Properties();
        try {
            p.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
       
        //取得配置文件中的值
        return p.getProperty(key);
    }
}

 

配置文件:config.properties

#配置索引路徑

indexPath=d:/LuceneIndex/LuceneTest02/

 

你需要導入幾個Jar文件:

lucene-core-2.4.1.jar(Lucene核心包)

lucene-highlighter-2.4.0.jar(用於高亮顯示的)

commons-logging.jar

paoding-analysis.jar(到網上搜索paoding-analysis-2.0.4-beta,解壓後把Jar拷貝過來就OK,把dic文件夾拷貝到工程的根目錄下,或者配置PAODING_DIC_HOME環境變量到bic目錄下)

 

工程結構:

 

運行結果:

 

這花費了 1672毫秒來把數據增加到索引裏面去!
共匹配到:2個.
檢索耗時: 109毫秒!
---------------
p_id:4
p_name:手錶4
p_price:16.29956430691176元
p_content:<b>手錶</b>的<b>描述</b><b>4</b>塊
---------------
---------------
p_id:3
p_name:手錶3
p_price:9.465650388124237元
p_content:<b>手錶</b>的<b>描述</b><b>3</b>塊
---------------

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章