1. 程式人生 > >Lucene4.10使用教程(四):lucene的Search

Lucene4.10使用教程(四):lucene的Search

package com.johnny.lucene02.search;

import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.io.ByteOrderMark;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.FuzzyQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.PhraseQuery;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TermRangeFilter;
import org.apache.lucene.search.TermRangeQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Version;
/**
 * 對於中文來說,Lucene提供的search基本上不能使用,使用中文分詞器替換即可
 * @author Johnny
 *
 */
public class SearchUtil {
    private Version Lucene_Version = Version.LUCENE_4_10_2;
    private Directory directory;
    private DirectoryReader reader = null;
    private String[] ids = {"1","2","3","4","5","6"};
    private String[] emails = {"
[email protected]
","[email protected]","[email protected]","[email protected]","[email protected]","[email protected]"};
    private String[] contents = {
            "welcome to visited the space,I like book java",
            "hello boy, I like pingpeng ball",
            "my name is cc I like game java",
            "I like football",
            "I like football and I like basketball too",
            "I like movie and swim java"
    };
    private Date[] dates = null;
    private int[] attachs = {2,3,1,4,5,5};
    private String[] names = {"zhangsan","lisi","john","jetty","mike","jake"};
    
    public SearchUtil() {
//        directory = new RAMDirectory();
        try {
            directory = FSDirectory.open(new File("/Users/ChinaMWorld/Desktop/index/"));
            setDates();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    private void setDates() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        try {
            dates = new Date[ids.length];
            dates[0] = sdf.parse("2010-02-19");
            dates[1] = sdf.parse("2012-01-11");
            dates[2] = sdf.parse("2011-09-19");
            dates[3] = sdf.parse("2010-12-22");
            dates[4] = sdf.parse("2012-01-01");
            dates[5] = sdf.parse("2011-05-19");
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    
    public void index() {
        IndexWriter writer = null;
        try {
            writer = new IndexWriter(directory,new IndexWriterConfig(Lucene_Version, new StandardAnalyzer()));
            //writer.deleteAll();
            Document doc = null;
            for(int i=0;i<ids.length;i++) {
                doc = new Document();
                doc.add(new StringField("id",ids[i],Store.YES));
                doc.add(new StringField("email", emails[i],Store.YES));
                doc.add(new TextField("content", contents[i], Store.NO));
                doc.add(new StringField("name",names[i], Store.YES));
                //儲存數字
                doc.add(new IntField("attach",attachs[i], Store.YES));
                //儲存日期
                doc.add(new LongField("date", dates[i].getTime(), Store.YES));
                
                String et = emails[i].substring(emails[i].lastIndexOf("@")+1);
                System.out.println(et);
                /**
                 * 在Lucene4.x中,只能給域加權,部門給文件加權,如果要提高文件的加權,需要給
                 * 文件的每個域進行加權
                 * **/
                
                writer.addDocument(doc);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
            try{
                if(writer!=null) writer.close();
            }catch(Exception ex){
                ex.printStackTrace();
            }
        }
    }
    
    public IndexSearcher getSearcher() {
        try {
            if(reader==null) {
                reader = DirectoryReader.open(directory);
            } else {
                DirectoryReader tr = DirectoryReader.openIfChanged(reader) ;
                if(tr!=null) {
                    reader.close();
                    reader = tr;
                }
            }
            return new IndexSearcher(reader);
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 指定field進行查詢,termquery不能進行數字和日期的查詢
     * 日期的查詢需要轉成數字進行查詢,
     * 數字查詢使用NumbericRangeQuery
     * @param field
     * @param name
     * @param num
     */
    public void searchByTerm(String field,String name,int num) {
        try {
            IndexSearcher searcher = getSearcher();
            Query query = new TermQuery(new Term(field,name));
            TopDocs tds = searcher.search(query, num);
            System.out.println("一共查詢了:"+tds.totalHits);
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(doc.get("id")+"---->"+
                        doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+
                        doc.get("attach")+","+doc.get("date"));
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    public void searchByTermRange(String field,String start,String end,int num) {
        try {
            IndexSearcher searcher = getSearcher();
            Query query = new TermRangeQuery(field,new BytesRef(start.getBytes()),new BytesRef(end.getBytes()) , true, true);
            TopDocs tds = searcher.search(query, num);
            System.out.println("一共查詢了:"+tds.totalHits);
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(doc.get("id")+"---->"+
                        doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+
                        doc.get("attach")+","+doc.get("date"));
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
    
    public void searchByQueryParse(Query query,int num) {
        try {
            IndexSearcher searcher = getSearcher();
            TopDocs tds = searcher.search(query, num);
            System.out.println("一共查詢了:"+tds.totalHits);
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                System.out.println(doc.get("id")+"---->"+
                        doc.get("name")+"["+doc.get("email")+"]-->"+doc.get("id")+","+
                        doc.get("attach")+","+doc.get("date")+"=="+sd.score);
            }
        } catch (CorruptIndexException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /***如果想要獲取為儲存到索引中得值,可以根據ID去原始檔中進行查詢並返回**/
    public void searchPage(String query,int pageIndex,int pageSize) {
        try {
            IndexSearcher searcher = getSearcher();
            QueryParser parser = new QueryParser("content",new StandardAnalyzer());
            Query q =null;
            try {
                q = parser.parse(query);
            } catch (org.apache.lucene.queryparser.classic.ParseException e) {
                e.printStackTrace();
            }
            TopDocs tds = searcher.search(q, 500);
            ScoreDoc[] sds = tds.scoreDocs;
            int start = (pageIndex-1)*pageSize;
            int end = pageIndex*pageSize;
            if(end>=sds.length) end = sds.length;
            for(int i=start;i<end;i++) {
                Document doc = searcher.doc(sds[i].doc);
                String id = doc.get("id");
                int arrInt = -1;
                for(int j=0;j<ids.length;j++){
                    if(id.equals(ids[j])){
                        arrInt = j;
                        break;
                    }
                }
                
                System.out.println(sds[i].doc+":"+doc.get("name")+"-->"+contents[arrInt]);
            }
            
        }  catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 根據頁碼和分頁大小獲取上一次的最後一個ScoreDoc
     */
    private ScoreDoc getLastScoreDoc(int pageIndex,int pageSize,Query query,IndexSearcher searcher) throws IOException {
        if(pageIndex==1)return null;//如果是第一頁就返回空
        int num = pageSize*(pageIndex-1);//獲取上一頁的數量
        TopDocs tds = searcher.search(query, num);
        return tds.scoreDocs[num-1];
    }
    /***
     * 在使用時,searchAfter查詢的是指定頁數後面的資料,效率更高,推薦使用
     * @param query
     * @param pageIndex
     * @param pageSize
     */
    public void searchPageByAfter(String query,int pageIndex,int pageSize) {
        try {
            IndexSearcher searcher = getSearcher();
            QueryParser parser = new QueryParser("content",new StandardAnalyzer());
            Query q = null;
            try {
                q = parser.parse(query);
            } catch (org.apache.lucene.queryparser.classic.ParseException e) {
                e.printStackTrace();
            }
            //先獲取上一頁的最後一個元素
            ScoreDoc lastSd = getLastScoreDoc(pageIndex, pageSize, q, searcher);
            //通過最後一個元素搜尋下頁的pageSize個元素
            TopDocs tds = searcher.searchAfter(lastSd,q, pageSize);
            for(ScoreDoc sd:tds.scoreDocs) {
                Document doc = searcher.doc(sd.doc);
                String id = doc.get("id");
                int arrInt = -1;
                for(int j=0;j<ids.length;j++){
                    if(id.equals(ids[j])){
                        arrInt = j;
                        break;
                    }
                }
                System.out.println(doc.get("name")+"-->"+contents[arrInt]);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    
    
}

測試程式碼如下:

相關推薦

Lucene4.10使用教程()lucene的Search

package com.johnny.lucene02.search; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; im

Spring Cloud 入門教程() 分布式環境下自動發現配置服務

.html article png discover ice conf label tail 註釋 前一章, 我們的Hello world應用服務,通過配置服務器Config Server獲取到了我們配置的hello信息“hello world”. 但自己的配置文件中必須配

Spring Boot系列教程配置文件詳解properties

date int ava ota axu return 端口 rand work 一.配置隨機數,使用隨機數 在application.properties文件添加配置信息 1 #32位隨機數 2 woniu.secret=${random.value} 3 #隨機整數

Shiro學習系列教程集成web(二)

shiro學習 凱哥java 本講主要內容:1:shiro對訪問URL可使用通配符進行匹配2:shiro標簽的使用3:shiro會話的機制URL匹配方式:演示:現在shiro.ini配置的路徑為:直接訪問/adminOk.沒問題。那麽我們訪問/admin1呢?就不行了。修改shiro.ini配置文件。

Spring Security教程()自定義登入頁

在前面的例子中,登陸頁面都是用的Spring Security自己提供的,這明顯不符合實際開發場景,同時也沒有退出和登出按鈕,因此在每次測試的時候都要通過關閉瀏覽器來登出達到清除session的效果。 一、自定義頁面 login.jsp: <%@ page language="

Java開發公眾號系列教程()公眾號訊息推送|事件訊息|模板訊息應用

今天分享一下公眾號推送模板訊息的開發案例。應用場景:使用者在公眾號上進行了一些操作後,公眾號自動向使用者推送相關的模板訊息,常見的比如使用者在公眾號付款後會收到商家的付款訊息提醒。接下來通過筆者在測試賬戶上的開發案例,效果如下:         &nb

Spring Boot基礎教程 ( ) Spring Boot 屬性配置檔案詳解

相信很多人選擇Spring Boot主要是考慮到它既能兼顧Spring的強大功能,還能實現快速開發的便捷。我們在Spring Boot使用過程中,最直觀的感受就是沒有了原來自己整合Spring應用時繁多的XML配置內容,替代它的是在pom.xml中引入模組化的Starter

Quartz教程Trigger

原文連結 | 譯文連結 | 翻譯:nkcoder 本系列教程由quartz-2.2.x官方文件翻譯、整理而來,希望給同樣對quartz感興趣的朋友一些參考和幫助,有任何不當或錯誤之處,歡迎指正;有興趣研究原始碼的同學,可以參考我對quartz-core原始碼的註釋(進行中)。 與job一樣,t

PostGIS教程載入空間資料

         在各種庫和應用程式的支援下,PostGIS提供了許多用於載入資料的選項。     本節將重點介紹使用PostGIS shapefile載入工具載入shapefile的基礎知識。 一、PostGIS s

熊大UWB系列教程UWB超寬頻三基站定位系統原理介紹與效果展示

對超寬頻感興趣的朋友,請關注熊大的微信公眾號,熊大將在上面釋出超寬頻教程,行業資訊,技術應用。幫助你更好的瞭解、學習、使用超寬頻技術。          購買熊大超寬頻系統,會提供微控制器原始碼,上位機原始碼還有技術支援。 熊大最近忙於開發超寬頻多基站多標籤定

MVC教程Controller向View傳值的幾種方式

一、通過ViewData傳值 MVC從開始版本就一直支援使用ViewData將Controller裡面的資料傳遞到View。ViewData定義如下: 從上面的截圖中可以看出,ViewData裡面存的是字典型別的資料,在檢視ViewDataDictionary的定義: 注意:ViewDataDi

教你如何開發VR遊戲系列教程UI 設計

這篇帖子主要介紹怎麼建立VR UI。 常見形式:1、2D NGUI、UGUI2、3D模型由於後續NGUI可能停止更新以及與U3d後續版本不相容問題,那麼主要就以UGUI為例。NGUI簡單說說。3D模型的話沒什麼好說,就跟普通VR場景一樣設定。2DUI,可以兩個螢幕都顯示

【QT】QT從零入門教程()選單欄、工具欄、狀態列

  選單欄、工具欄、工作列是軟體中常見的元件,本節將會講解如何建立選單欄並生成一級選單、二級選單,如何在工具欄中新增圖示和控制元件,如何在工作列中顯示文字。 標題及圖示 // 標題大小 setWindowTitle("影象處理自編軟體 by

Google Map API Version3 教程()給marker標記加上自定義內容

      lat = 23.14746;       lng = 113.34175376;       var myLatLng = new google.maps.LatLng(lat, lng);       var myOptions = {           zoom: 15,        

springcloud 系列教程服務消費者(Feign)

一、Feign簡介 Feign 的英文表意為 "假裝,偽裝,變形", 是一個http請求呼叫的輕量級框架,可

WebGL簡易教程()顏色

目錄 1. 概述 2. 示例:繪製三角形 1) 資料的組織 2) varying變數 3. 結果 4. 理解 1) 圖形裝配和光柵化

Lucene4.10使用教程(六)Lucene的過濾器

package com.johnny.lucene04.advance_search; import java.io.IOException; import org.apache.lucene.index.AtomicReaderContext; import org.apache.lucene.index.

Lucene4.10使用教程(九)Tika

package com.johnny.lucene05.lucene_plugin.tika; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import org.apache.commons.

《C#圖解教程》讀書筆記之類和繼承

intern html pan 類中訪問 ted obj 小寫 his new 本篇已收錄至《C#圖解教程》讀書筆記目錄貼,點擊訪問該目錄可獲取更多內容。 一、萬物之宗:Object   (1)除了特殊的Object類,其他所有類都是派生類,即使他們沒有顯示基類定義。   

Spring 基礎教程JavaBean基本配置詳解

一:xml 裝配JavaBean屬性含義: 1.id:指定該Bean 的唯一標識。 2.class:指定該Bean 的全限定名。 3.name:為該Bean 指定一到多個別名。多個別名可以用“,”和“;”分割。