lucene全文檢索索引多種查詢檢索簡單案例__lucene

來源:互聯網
上載者:User

針對lucene全文檢索索引引擎寫一下多種查詢檢索的方式

這裡採用的是英文分詞,單獨寫了一篇關於中文分詞與高亮顯示,如下:
lucene全文檢索索引之 中文分詞 以及 高亮顯示,點擊進入

另外分享一個 lucene索引庫查看器 ,點擊進入

lucene官網 http://lucene.apache.org這裡寫連結內容

首先需要引入lucene的maven依賴,如下:

<dependency>    <groupId>org.apache.lucene</groupId>    <artifactId>lucene-core</artifactId>    <version>5.3.1</version></dependency><dependency>    <groupId>org.apache.lucene</groupId>    <artifactId>lucene-queryparser</artifactId>    <version>5.3.1</version></dependency><dependency>    <groupId>org.apache.lucene</groupId>    <artifactId>lucene-analyzers-common</artifactId>    <version>5.3.1</version></dependency>

下面我就直接貼代碼吧,如下:

package luceneDemo;import java.io.IOException;import java.nio.file.Paths;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import org.apache.lucene.analysis.Analyzer;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.TextField;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.IndexSearcher;import org.apache.lucene.search.Query;import org.apache.lucene.search.ScoreDoc;import org.apache.lucene.search.TermQuery;import org.apache.lucene.search.TopDocs;import org.apache.lucene.store.Directory;import org.apache.lucene.store.FSDirectory;import org.apache.lucene.search.TermRangeQuery;import org.apache.lucene.util.BytesRef;import org.apache.lucene.search.NumericRangeQuery;import org.apache.lucene.search.PrefixQuery;import org.apache.lucene.search.BooleanClause;import org.apache.lucene.search.BooleanQuery;/** * 全文檢索索引案例 * @author mszhou */public class luceneDemo {    /**     * 示範將資料寫入索引檔案中     * 在項目中我們會定時將資料寫入索引檔案中,     * 然後在索引檔案中進行搜尋,這樣比在資料庫中搜尋效率高的多,     * 而且檢索遠比資料庫的模糊比對強大的多,這也是檢索工具牛逼之處     *      * 需要注意的是,如果在項目中定時寫入索引,     * 需要判斷下該資料是否存在,存在則修改,不存在再進行新增     *      * @param luceneDir 該參數表示索引所存放的目錄     */    public static void writeIndex(String luceneDir){        IndexWriter writer = null;//聲明建立索引寫入器         try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立標準分詞器(一般英文使用這個,不適合中文使用)            Analyzer analyzer=new StandardAnalyzer(); // 標準分詞器            IndexWriterConfig iwc=new IndexWriterConfig(analyzer);            //建立索引寫入器執行個體,通過IndexWriterConfig設定相關配置            writer=new IndexWriter(dir, iwc);            //=== 這裡造一些資料用作示範,也可以直接讀取資料庫中的資料 開始========            List <Map<String,String>> list=new ArrayList<Map<String,String>>();            //假資料1             Map<String,String> map1 =new HashMap<String, String>();            map1.put("title", "weejij dasa ");//表示標題欄位            map1.put("centent", "hdaiads sd s g r44e r hgg f hd 4 ");//表示標題欄位            list.add(map1);            //假資料2             Map<String,String> map2 =new HashMap<String, String>();            map2.put("title", "demo12 i33s ss");//表示標題欄位            map2.put("centent", "hdaiads sd s g r44e r hgg f hd 4 ");//表示標題欄位               list.add(map2);            //假資料1             Map<String,String> map3 =new HashMap<String, String>();            map3.put("title", "demo 12i131s ss");//表示標題欄位            map3.put("centent", "hdaiads sd s g r44e r hgg f hd 4 ");//表示標題欄位               list.add(map3);            //=== 這裡造一些資料用作示範,也可以直接讀取資料庫中的資料 結束========            //遍曆資料,並且將資料寫入到索引中            for(int i=0 ;i<list.size();i++){                // ======   擷取資料開始 ======                 Map<String,String> mapCen=list.get(i);                String title =  mapCen.get("title").toString();//擷取標題                String centent = mapCen.get("centent").toString();//擷取內容                // ======   擷取資料結束 ======                 //========= 將資料寫入索引開始  =================                //建立Document對象,Document表示lucene索引的資料結構單元                Document doc=new Document();                //添加id 資料,最後面Field.Store.YES表示儲存該欄位                doc.add(new IntField("id", i,  Field.Store.YES));                /*添加標題資料,最後面Field.Store.YES 表示儲存該欄位                 *注意:如果需要檢索該欄位,建議使用TextField類型,並且設定為 Field.Store.YES                 */                doc.add(new TextField("title",title , Field.Store.YES));                //添加標題內容資料,最後面Field.Store.NO  表示不儲存該欄位                doc.add(new TextField("centent", centent, Field.Store.NO));                // 寫入索引                writer.addDocument(doc);                 //========= 將資料寫入索引結束  =================            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                writer.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }    }    /**     * 示範對特定項搜尋     * @param luceneDir 該參數表示索引所存放的目錄     * @param field 表示需要搜尋的項(就是寫入時屬性欄位名稱)     * @param qu 需要檢索的關鍵詞     */    public static void testTermQuery(String luceneDir,String field, String qu){        IndexReader reader = null;//聲明索引讀取器        try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立索引讀取器            reader=DirectoryReader.open(dir);            //建立索引搜尋器            IndexSearcher is=new IndexSearcher(reader);            //建立查詢器,參數field表示屬性欄位,qu表示檢索的關鍵詞            Term t=new Term(field,qu);            Query query=new TermQuery(t);            //這裡查詢前10條匹配的資料,第二個參數為10表示查前十條            TopDocs hits=is.search(query, 10);            //列印            System.out.println("檢索文檔欄位"+ field +" ,匹配 "+qu+" , 查詢到"+hits.totalHits+"個記錄");            //遍曆查詢到的資料            for(ScoreDoc scoreDoc:hits.scoreDocs){                Document doc=is.doc(scoreDoc.doc);                String id  = doc.get("id")==null?"":doc.get("id").toString();//擷取id                String title  = doc.get("title")==null?"":doc.get("title").toString();//擷取標題                //由於寫入的時候 ,設定了Field.Store.NO 表示不儲存該欄位,所以這裡讀取不到                //String centent  = doc.get("centent")==null"":doc.toString();//擷取內容                //列印資料                System.out.println("id是:"+id+" ,標題是:"+title);            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                reader.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }    }    /**     * 示範解析查詢運算式(這裡示範查詢title欄位屬性)     * @param luceneDir 該參數表示索引所存放的目錄     * @param titleStr 需要檢索的關鍵詞     */    public static void testQueryParser(String luceneDir,String titleStr){        IndexReader reader = null;//聲明索引讀取器        try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立索引讀取器            reader=DirectoryReader.open(dir);            //建立索引搜尋器            IndexSearcher is=new IndexSearcher(reader);            //建立標準分詞器(一般英文使用這個,不適合中文使用)            Analyzer analyzer=new StandardAnalyzer(); // 標準分詞器            //建立QueryParser查詢器,查詢title屬性欄位            QueryParser parser=new QueryParser("title", analyzer);            //設定查詢關鍵詞            Query query=parser.parse(titleStr);            //這裡查詢前10條匹配的資料,第二個參數為10表示查前十條            TopDocs hits=is.search(query, 10);            //列印資訊            System.out.println("匹配 "+titleStr+" , 查詢到"+hits.totalHits+"個記錄");            //遍曆查詢到的資料            for(ScoreDoc scoreDoc:hits.scoreDocs){                Document doc=is.doc(scoreDoc.doc);                String id  = doc.get("id")==null?"":doc.get("id").toString();//擷取id                String title  = doc.get("title")==null?"":doc.get("title").toString();//擷取標題                //由於寫入的時候 ,設定了Field.Store.NO 表示不儲存該欄位,所以這裡讀取不到                //String centent  = doc.get("centent").toString();//擷取內容                //列印資料                System.out.println("id是:"+id+" ,標題是:"+title);            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                reader.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }    }    /**     * 示範指定項範圍搜尋     * @param luceneDir 該參數表示索引所存放的目錄     */    public static void testTermRangeQuery(String luceneDir){        IndexReader reader = null;//聲明索引讀取器        try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立索引讀取器            reader=DirectoryReader.open(dir);            //建立索引搜尋器            IndexSearcher is=new IndexSearcher(reader);            /*             * 建立TermRangeQuery查詢器,查詢title屬性欄位 從a到e範圍內             * 一般對於英文來說,進行ASC碼範圍查詢還有那麼一點意義,             * 中文漢字進行ASC碼值比較沒什麼太大意義,             * 一般數字範圍查詢NumericRangeQuery用的比較多一點,             * 比如價格,年齡,金額,數量等等都涉及到數字,數字範圍查詢需求也很普遍             *              * 後面兩個boolean值用來控制是否包含兩個上下邊界值的。             */            TermRangeQuery query=new TermRangeQuery("title", new BytesRef("a".getBytes()), new BytesRef("e".getBytes()), true, true);            //這裡查詢前10條匹配的資料,第二個參數為10表示查前十條            TopDocs hits=is.search(query, 10);            //遍曆查詢到的資料            for(ScoreDoc scoreDoc:hits.scoreDocs){                Document doc=is.doc(scoreDoc.doc);                String id  = doc.get("id")==null?"":doc.get("id").toString();//擷取id                String title  = doc.get("title")==null?"":doc.get("title").toString();//擷取標題                                //列印資料                System.out.println("id是:"+id+" ,標題是:"+title);            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                reader.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }           }    /**     * 示範指定數字範圍     * @param luceneDir  該參數表示索引所存放的目錄     */    public static void testNumericRangeQuery(String luceneDir){        IndexReader reader = null;//聲明索引讀取器        try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立索引讀取器            reader=DirectoryReader.open(dir);            //建立索引搜尋器            IndexSearcher is=new IndexSearcher(reader);            /*             * 建立NumericRangeQuery查詢器,查詢id屬性欄位 從1到2範圍內             *              * 後面兩個boolean值用來控制是否包含兩個上下邊界值的。             */            NumericRangeQuery<Integer> query=NumericRangeQuery.newIntRange("id", 1, 2, true, true);            //這裡查詢前10條匹配的資料,第二個參數為10表示查前十條            TopDocs hits=is.search(query, 10);            //遍曆查詢到的資料            for(ScoreDoc scoreDoc:hits.scoreDocs){                Document doc=is.doc(scoreDoc.doc);                String id  = doc.get("id")==null?"":doc.get("id").toString();//擷取id                String title  = doc.get("title")==null?"":doc.get("title").toString();//擷取標題                                //列印資料                System.out.println("id是:"+id+" ,標題是:"+title);            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                reader.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }       }    /**     * 示範指定字串開頭搜尋     * @param luceneDir  該參數表示索引所存放的目錄     */    public static void testPrefixQuery(String luceneDir){        IndexReader reader = null;//聲明索引讀取器        try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立索引讀取器            reader=DirectoryReader.open(dir);            //建立索引搜尋器            IndexSearcher is=new IndexSearcher(reader);            /*             * 建立NumericRangeQuery查詢器,             * 查詢title屬性欄位分詞索引以 w 開頭的資料             */            PrefixQuery query=new PrefixQuery(new Term("title","w"));            //這裡查詢前10條匹配的資料,第二個參數為10表示查前十條            TopDocs hits=is.search(query, 10);            //遍曆查詢到的資料            for(ScoreDoc scoreDoc:hits.scoreDocs){                Document doc=is.doc(scoreDoc.doc);                String id  = doc.get("id")==null?"":doc.get("id").toString();//擷取id                String title  = doc.get("title")==null?"":doc.get("title").toString();//擷取標題                                //列印資料                System.out.println("id是:"+id+" ,標題是:"+title);            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                reader.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }    }    /**     * 示範多條件查詢     * @param luceneDir 該參數表示索引所存放的目錄     */    public static void testBooleanQuery(String luceneDir){        IndexReader reader = null;//聲明索引讀取器        try{            //建立索引目錄 , 這裡參數luceneDir 表示索引存放目錄            Directory dir=FSDirectory.open(Paths.get(luceneDir));            //建立索引讀取器            reader=DirectoryReader.open(dir);            //建立索引搜尋器            IndexSearcher is=new IndexSearcher(reader);            //========== 建立多個查詢條件 開始===============            BooleanQuery.Builder booleanQuery=new BooleanQuery.Builder();            /*             * 條件1,             * 建立NumericRangeQuery查詢器,查詢id屬性欄位 從1到2範圍內             * 後面兩個boolean值用來控制是否包含兩個上下邊界值的。             */            NumericRangeQuery<Integer> query1=NumericRangeQuery.newIntRange("id", 1, 2, true, true);            /*             * 添加查詢條件1 到組合查詢器中             * BooleanClause.Occur.MUST 表示與 (相當於並且)             * BooleanClause.Occur.SHOULD 表示或 (相當於或者)             * BooleanClause.Occur.MUST_NOT 表示不包含 (相當於not)             */            booleanQuery.add(query1,BooleanClause.Occur.MUST);            /*             * 條件2,              * 建立NumericRangeQuery查詢器,             * 查詢title屬性欄位分詞索引以 12 開頭的資料             */            PrefixQuery query2=new PrefixQuery(new Term("title","12"));            /*             * 添加查詢條件2 到組合查詢器中             * BooleanClause.Occur.MUST 表示與 (相當於並且)             * BooleanClause.Occur.SHOULD 表示或 (相當於或者)             * BooleanClause.Occur.MUST_NOT 表示不包含 (相當於not)             */            booleanQuery.add(query2,BooleanClause.Occur.MUST);            //========== 建立多個查詢條件 結束===============            /*             * 這裡查詢前10條匹配的資料,第二個參數為10表示查前十條             * 這裡查詢檢索表示滿足條件1並且同時滿足條件2的資料             */            TopDocs hits=is.search(booleanQuery.build(), 10);            //遍曆查詢到的資料            for(ScoreDoc scoreDoc:hits.scoreDocs){                Document doc=is.doc(scoreDoc.doc);                String id  = doc.get("id")==null?"":doc.get("id").toString();//擷取id                String title  = doc.get("title")==null?"":doc.get("title").toString();//擷取標題                                //列印資料                System.out.println("id是:"+id+" ,標題是:"+title);            }        }catch(Exception e){            System.out.println("發生了異常!");            e.printStackTrace();        }finally{            try {                reader.close();//關閉流,一定要記得關閉            } catch (IOException e) {            }        }    }    /**     * 測試上面的方法     * @param args     * @throws Exception     */    public static void main(String[] args) throws Exception {        //表示索引目錄        String luceneDir =  "D://lucene";        //測試該方法寫入資料到索引檔案中        //writeIndex(luceneDir);        //測試檢索屬性欄位title,檢索關鍵詞為demo        //testTermQuery(luceneDir,"title", "de

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.