Lucene介紹及簡單入門案例(集成ik分詞器)
介紹
Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。Lucene的目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。Lucene是一套用於全文檢索和搜尋的開源程式庫,由Apache軟件基金會支持和提供。Lucene提供了一個簡單卻強大的應用程式接口,能夠做全文索引和搜尋。在Java開發環境裏Lucene是一個成熟的免費開源工具。就其本身而言,Lucene是當前以及最近幾年最受歡迎的免費Java信息檢索程序庫。人們經常提到信息檢索程序庫,雖然與搜索引擎有關,但不應該將信息檢索程序庫與搜索引擎相混淆。
Lucene是Apache提供的一個開源的全文檢索引擎工具包, 其本質就是一個工具包, 而非一個完整的搜索引擎, 但是我們可以通過Lucene來構建一個搜索引擎,比如solr和elasticsearch都是基於Lucene的搜索引擎。
使用Lucene如何構建索引
第一步:導入相關的jar包
<dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-core</artifactId> <version>4.10.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queries</artifactId> <version>4.10.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-test-framework</artifactId> <version>4.10.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-analyzers-common</artifactId> <version>4.10.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-queryparser</artifactId> <version>4.10.2</version> </dependency> <dependency> <groupId>org.apache.lucene</groupId> <artifactId>lucene-highlighter</artifactId> <version>4.10.2</version> </dependency>
第二步:書寫寫入索引的代碼
簡單案例:
public class LuceneIndex { public static void main(String[] args) throws IOException { //1 創建indexwriter對象 //1.1 創建索引庫 FSDirectory directory = FSDirectory.open(new File("H:\\test")); //1.2 創建寫入器配置對象 參數1 版本號, 參數2 分詞器 IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new StandardAnalyzer()); //1.3 創建indexwriter對象 IndexWriter indexWriter = new IndexWriter(directory, config); //2 寫入文檔 //2.1 創建文檔對象(lucene的document對象) Document document = new Document(); //2.2 添加文檔屬性(字段) new xxxField(字段名,字段值,是否保存) document.add(new IntField("id", 1, Field.Store.YES)); document.add(new StringField("title", "Lucene介紹", Field.Store.YES)); document.add(new TextField("content", "Lucene是一個全文檢索的工具包", Field.Store.YES)); //2.3 寫入文檔 indexWriter.addDocument(document); //3 提交數據 indexWriter.commit(); //釋放資源 indexWriter.close(); } }
使用索引查看工具查看插入的索引信息
下載一個lukeall-xxxx(版本信息).jar, cmd運行這個工具jar包:
Lucene集成IKAnalyzer 中文分詞器
? 用於對文檔中的數據進行分詞, 其分詞的效果取決於分詞器的選擇, Lucene中根據各個國家制定了各種語言的分詞器,對中文有一個ChineseAnalyzer 但是其分詞的效果, 是將中文進行一個一個字的分開
針對中文分詞一般只能使用第三方的分詞詞,比如IKAnalyzer
首先要引入jar包:
<!-- 引入IK分詞器 --> <dependency> <groupId>com.janeluo</groupId> <artifactId>ikanalyzer</artifactId> <version>2012_u6</version> </dependency>
代碼部分只需要修改我們上面案例的分詞器對象即可:
//1.2 創建寫入器配置對象 參數1 版本號, 參數2 分詞器 IndexWriterConfig config = new IndexWriterConfig(Version.LATEST, new IKAnalyzer());
ik分詞器在2012年更新後, 就在沒有更新, 其原因就取決於其強大的擴展功能,以保證ik能夠持續使用
ik支持對自定義詞庫, 其可以定義兩個擴展的詞典
1) 擴展詞典(新創建詞功能):有些詞IK分詞器不識別 例如:“劍來”,“劍九黃”
2) 停用詞典(停用某些詞功能)有些詞不需要建立索引 例如:“哦”,“啊”,“的”
如何使用:
在resources內創建者三個文件,在ext.dic中設置需要進行分詞的內容即可, 在stopword中設置不被分詞的內容即可,xml文件內容格式如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd"> <properties> <comment>IK Analyzer 擴展配置</comment> <!--用戶可以在這裏配置自己的擴展字典 --> <entry key="ext_dict">ext.dic;</entry> <!--用戶可以在這裏配置自己的擴展停止詞字典--> <entry key="ext_stopwords">stopword.dic;</entry> </properties>
其他兩個詞典內容格式:
劍來
劍九黃
劍開天門
API詳解:
-
其主要的作用, 添加索引, 修改索引和刪除索引
-
創建此對象的時候, 需要傳入Directory和indexWriterConfig對象
-
-
Directory: 目錄類, 用來指定索引庫的目錄
-
常用的實現類:
-
FSDirectory: 用來指定文件系統的目錄, 將索引信息保存到磁盤上
-
優點: 索引可以進行長期保存, 安全系數高
-
缺點: 讀取略慢
-
-
RAMDriectory: 內存目錄, 將索引庫信息存放到內存中
-
優點: 讀取速度快
-
缺點: 不安全, 無法長期保存, 關機後就消失了
-
-
-
-
IndexWriterConfig: 索引寫入器的配置類
-
創建此對象, 需要傳遞Lucene的版本和分詞器
-
作用:
-
作用1 : 指定Lucene的版本和需要使用的分詞器
-
作用2: 設置Lucene的打開索引庫的方式: setOpenMode();
-
//參數值: APPEND CREATE CREATE_OR_APPEND /** * APPEND: 表示追加, 如果索引庫存在, 就會向索引庫中追加數據, 如果索引庫不存在, 直接報錯 * * CREATE: 表示創建, 不管索引庫有沒有, 每一次都是重新創建一個新的索引庫 * * CREATE_OR_APPEND: 如果索引庫有, 就會追加, 如果沒有 就會創建索引庫 默認值也是 CREATE_OR_APPEND */ config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
? 在Lucene中, 每一條數據以文檔的形式進行存儲, 文檔中也有其對應的屬性和值, Lucene中一個文檔類似數據庫的一個表, 表中的字段類似於文檔中的字段,只不過這個文檔只能保存一條數據
? Document看做是一個文件, 文件的屬性就是文檔的屬性, 文件對應屬性的值就是文檔的屬性的值 content
-
一個文檔中可以有多個字段, 每一個字段就是一個field對象,不同的文檔可以有不同的屬性
-
字段也有其對應數據類型, 故Field類也提供了各種數據類型的實現類
Field類 | 數據類型 | Analyzed是否分析 | Indexed是否索引 | Stored是否存儲 | 說明 |
---|---|---|---|---|---|
StringField(FieldName, FieldValue,Store.YES)) | 字符串 | N | Y | Y或N | 這個Field用來構建一個字符串Field,但是不會進行分析,會將整個串存儲在索引中,比如(訂單號,姓名等)是否存儲在文檔中用Store.YES或Store.NO決定 |
LongField(FieldName, FieldValue,Store.YES) | Long型 | Y | Y | Y或N | 這個Field用來構建一個Long數字型Field,進行分析和索引,比如(價格)是否存儲在文檔中用Store.YES或Store.NO決定 |
StoredField(FieldName, FieldValue) | 重載方法,支持多種類型 | N | N | Y | 這個Field用來構建不同類型Field不分析,不索引,但要Field存儲在文檔中 |
TextField(FieldName, FieldValue, Store.NO)或TextField(FieldName, reader) | 字符串或流 | Y | Y | Y或N | 如果是一個Reader, lucene猜測內容比較多,會采用Unstored的策略. |
更改和刪除索引:
/** * 更新索引 * 本質先刪除再添加 * 先刪除所有滿足條件的文檔,再創建文檔 * 因此,更新索引通常要根據唯一字段 */ @Test public void testUpdate() throws Exception { // 創建更改後的文檔對象 Document document = new Document(); document.add(new StringField("id", "3", Field.Store.YES)); document.add(new TextField("title", "更改後的titlek", Field.Store.YES)); // 索引庫對象 Directory directory = FSDirectory.open(new File("H:\\test")); // 索引寫入器配置對象 IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer()); // 索引寫入器對象 IndexWriter indexWriter = new IndexWriter(directory, conf); // 執行更新操作 參數1 要更改的對象, 參數2 更改後的對象 indexWriter.updateDocument(new Term("id", "1"), document); // 提交 indexWriter.commit(); // 關閉 indexWriter.close(); } // 刪除索引 @Test public void testDelete() throws Exception { // 創建目錄對象 Directory directory = FSDirectory.open(new File("H:\\test")); // 創建索引寫入器配置對象 IndexWriterConfig conf = new IndexWriterConfig(Version.LATEST, new IKAnalyzer()); // 創建索引寫入器對象 IndexWriter indexWriter = new IndexWriter(directory, conf); // 執行刪除操作(根據詞條),要求id字段必須是字符串類型 indexWriter.deleteDocuments(new Term("id", "5")); // 根據查詢條件刪除 // indexWriter.deleteDocuments(NumericRangeQuery.newLongRange("id", 2l, 4l, true, false)); // 刪除所有 //indexWriter.deleteAll(); // 提交 indexWriter.commit(); // 關閉 indexWriter.close(); }
Lucene介紹及簡單入門案例(集成ik分詞器)