問題1:索引建立過程完成什麼事?java
分詞、存儲到反向索引中git
1. 回顧Lucene架構圖:github
介紹咱們編寫的應用程序要完成數據的收集,再將數據以document的形式用lucene的索引API建立索引、存儲。 這裏重點要強調應用代碼負責作什麼,lucene負責作什麼。數據庫
2. Lucene索引建立API 圖示apache
經過該圖介紹lucene建立索引的核心API:Document、IndexWriter數組
Lucene中要索引的文檔、數據記錄以document表示,應用程序經過IndexWirter將Document加入到索引中。緩存
3. Lucene索引建立代碼示例 安全
public static void main(String[] args) throws IOException { // 建立使用的分詞器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); // 索引配置對象 IndexWriterConfig config = new IndexWriterConfig(analyzer); // 設置索引庫的打開模式:新建、追加、新建或追加 config.setOpenMode(OpenMode.CREATE_OR_APPEND); // 索引存放目錄 // 存放到文件系統中 Directory directory = FSDirectory .open((new File("f:/test/indextest")).toPath()); // 存放到內存中 // Directory directory = new RAMDirectory(); // 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config); // 建立document Document doc = new Document(); // 往document中添加 商品id字段 doc.add(new StoredField("prodId", "p0001")); // 往document中添加 商品名稱字段 String name = "ThinkPad X1 Carbon 20KH0009CD/25CD 超極本輕薄筆記本電腦聯想"; doc.add(new TextField("name", name, Store.YES)); // 將文檔添加到索引 writer.addDocument(doc); // ..... // 刷新 writer.flush(); // 提交 writer.commit(); // 關閉 會提交 writer.close(); directory.close(); }
上面示例代碼對應的類圖展現:架構
4. IndexWriterConfig 寫索引配置:ide
使用的分詞器,
如何打開索引(是新建,仍是追加)。
還可配置緩衝區大小、或緩存多少個文檔,再刷新到存儲中。
還可配置合併、刪除等的策略。
注意:
用這個配置對象建立好IndexWriter對象後,再修改這個配置對象的配置信息不會對IndexWriter對象起做用。
如要在indexWriter使用過程當中修改它的配置信息,經過 indexWriter的getConfig()方法得到 LiveIndexWriterConfig 對象,在這個對象中可查看該IndexWriter使用的配置信息,可進行少許的配置修改(看它的setter方法)
5. Directory 指定索引數據存放的位置
內存
文件系統
數據庫
保存到文件系統用法: Directory directory = FSDirectory.open(Path path); // path指定目錄
保存到內存中用法:Directory directory = new RAMDirectory();
6. IndexWriter 用來建立、維護一個索引 。它的API使用流程:
// 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config); // 建立document // 將文檔添加到索引 writer.addDocument(doc); // 刪除文檔 //writer.deleteDocuments(terms); //修改文檔 //writer.updateDocument(term, doc); // 刷新 writer.flush(); // 提交 writer.commit();
注意:IndexWriter是線程安全的。 若是你的業務代碼中有其餘的同步控制,請不要使用IndexWriter做爲鎖對象,以避免死鎖。
IndexWriter涉及類圖示:
問題2: 索引庫中會存儲反向索引數據,會存儲document嗎?
索引庫會存儲一下關鍵的document信息
問:在百度、天貓上進行搜索,展現的列表中的數據來自哪裏?源DB、FS 嗎?
存在索引庫裏
1. Document 文檔
要索引的數據記錄、文檔在lucene中的表示,是索引、搜索的基本單元。一個Document由多個字段Field構成。就像數據庫的記錄-字段。
IndexWriter按加入的順序爲Document指定一個遞增的id(從0開始),稱爲文檔id。反向索引中存儲的是這個id,文檔存儲中正向索引也是這個id。 業務數據的主鍵id只是文檔的一個字段。
Document API
2. Field
字段:由字段名name、字段值value(fieldsData)、字段類型 type 三部分構成。
字段值能夠是文本(String、Reader 或 預分析的 TokenStream)、二進制值(byte[])或數值。
IndexableField Field API
3. Document—Field 數據舉例
新聞:新聞id,新聞標題、新聞內容、做者、所屬分類、發表時間
網頁搜索的網頁:標題、內容、連接地址
商品: id、名稱、圖片連接、類別、價格、庫存、商家、品牌、月銷量、詳情…
問題1:咱們收集數據建立document對象來爲其建立索引,數據的全部屬性是否都須要加入到document中?如數據庫表中的數據記錄的全部字段是否都須要放到document中?哪些字段應加入到document中?
看具體的業務,只有須要被搜索和展現的字段才須要被加入到document中
問題2:是否是全部加入的字段都須要進行索引?是否是全部加入的字段都要保存到索引庫中?什麼樣的字段該被索引?什麼樣的字段該被存儲?
看具體的業務,須要被搜索的字段才該被索引,須要被展現的字段該被存儲
問題3:各類要被索引的字段該以什麼樣的方式進行索引,全都是分詞進行索引,仍是有不一樣區別?
看是模糊查詢仍是精確查詢,模糊查詢的話就須要被分詞索引,精確查詢的話就不須要被分詞索引
4. IndexableFieldType
字段類型:描述該如何索引存儲該字段。
字段可選擇性地保存在索引中,這樣在搜索結果中,這些保存的字段值就可得到。
一個Document應該包含一個或多個存儲字段來惟一標識一個文檔。爲何?
爲從原數據中拿完整數據去展現
5. Document 類關係
IndexableFieldType API 說明
6. IndexOptions 索引選項說明:
NONE:Not indexed 不索引
DOCS: 反向索引中只存儲了包含該詞的 文檔id,沒有詞頻、位置
DOCS_AND_FREQS: 反向索引中會存儲 文檔id、詞頻
DOCS_AND_FREQS_AND_POSITIONS:反向索引中存儲 文檔id、詞頻、位置
DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS :反向索引中存儲 文檔id、詞頻、位置、偏移量
package com.study.lucene.indexdetail; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import com.study.lucene.ikanalyzer.Integrated.IKAnalyzer4Lucene7; /** * 索引選項選擇 * * @author THINKPAD * */ public class IndexOptionsDemo { public static void main(String[] args) { // 建立使用的分詞器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); // 索引配置對象 IndexWriterConfig config = new IndexWriterConfig(analyzer); try ( // 索引存放到文件系統中 Directory directory = FSDirectory.open((new File("f:/test/indextest")).toPath()); // 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config);) { // 準備document Document doc = new Document(); // 字段content String name = "content"; String value = "張三說的確實在理"; FieldType type = new FieldType(); // 設置是否存儲該字段 type.setStored(true); // 請試試不存儲的結果 // 設置是否對該字段分詞 type.setTokenized(true); // 請試試不分詞的結果 // 設置該字段的索引選項 type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS); // 請嘗試不一樣的選項的效果 type.freeze(); // 使不可更改 Field field = new Field(name, value, type); // 添加字段 doc.add(field); // 加入到索引中 writer.addDocument(doc); } catch (IOException e) { e.printStackTrace(); } } }
問題4:若是要在搜索結果中作關鍵字高亮,須要什麼信息?若是要實現短語查詢、臨近查詢(跨度查詢),須要什麼信息?
如 要搜索包含「張三」 「李四」,且兩詞之間跨度不超過5個字符 。
須要位置和偏移量
問題5:位置、偏移數據在反向索引中佔的存儲量佔比大不大?
看分詞的數據量
問題6:若是某個字段不須要進行短語查詢、臨近查詢,那麼在反向索引中就不須要保存位置、偏移數據。這樣是否是能夠下降反向索引的數據量,提高效率?可是若是該字段要作高亮顯示支持,該怎麼辦?。
爲了提高反向索引的效率,這樣的字段的位置、偏移數據是不該該保存到反向索引中的。這也你前面看到 IndexOptions爲何有那些選項的緣由。
一個字段分詞器分詞後,每一個詞項會獲得一系列屬性信息,如 出現頻率、位置、偏移量等,這些信息構成一個詞項向量 termVectors
7. IndexableFieldType API
storeTermVectors:
對於不須要在搜索反向索引時用到,但在搜索結果處理時須要的位置、偏移量、附加數據(payLoad) 的字段,咱們能夠單獨爲該字段存儲(文檔id詞項向量)的正向索引。
示例代碼:
package com.study.lucene.indexdetail; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import com.study.lucene.ikanalyzer.Integrated.IKAnalyzer4Lucene7; /** * 詞向向量 * @author THINKPAD * */ public class IndexTermVectorsDemo { public static void main(String[] args) { // 建立使用的分詞器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); // 索引配置對象 IndexWriterConfig config = new IndexWriterConfig(analyzer); try ( // 索引存放到文件系統中 Directory directory = FSDirectory .open((new File("f:/test/indextest")).toPath()); // 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config);) { // 準備document Document doc = new Document(); // 字段content String name = "content"; String value = "張三說的確實在理"; FieldType type = new FieldType(); // 設置是否存儲該字段 type.setStored(true); // 請試試不存儲的結果 // 設置是否對該字段分詞 type.setTokenized(true); // 請試試不分詞的結果 // 設置該字段的索引選項 type.setIndexOptions(IndexOptions.DOCS); // 反向索引中只保存詞項 // 設置爲該字段保存詞項向量 type.setStoreTermVectors(true); type.setStoreTermVectorPositions(true); type.setStoreTermVectorOffsets(true); type.setStoreTermVectorPayloads(true); type.freeze(); // 使不可更改 Field field = new Field(name, value, type); // 添加字段 doc.add(field); // 加入到索引中 writer.addDocument(doc); } catch (IOException e) { e.printStackTrace(); } } }
請爲商品記錄創建索引,字段信息以下:
商品id:字符串,不索引、但存儲
String prodId = "p0001";
商品名稱:字符串,分詞索引(存儲詞頻、位置、偏移量)、存儲
String name = 「ThinkPad X1 Carbon 20KH0009CD/25CD 超極本輕薄筆記本電腦";
圖片連接:僅存儲
String imgUrl = "http://www.cnblogs.com/leeSmall/";
商品簡介:字符串,分詞索引(不須要支持短語、臨近查詢)、存儲,結果中支持高亮顯示
String simpleIntro = "集成顯卡 英特爾 酷睿 i5-8250U 14英寸";
品牌:字符串,不分詞索引,存儲
String brand = "ThinkPad";
package com.study.lucene.indexdetail; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.NumericUtils; import com.study.lucene.ikanalyzer.Integrated.IKAnalyzer4Lucene7; /** * 爲商品記錄創建索引 * @author THINKPAD * */ public class ProductIndexExercise { public static void main(String[] args) { // 建立使用的分詞器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); // 索引配置對象 IndexWriterConfig config = new IndexWriterConfig(analyzer); try ( // 索引存放目錄 // 存放到文件系統中 Directory directory = FSDirectory .open((new File("f:/test/indextest")).toPath()); // 存放到內存中 // Directory directory = new RAMDirectory(); // 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config);) { // 準備document Document doc = new Document(); // 商品id:字符串,不索引、但存儲 String prodId = "p0001"; FieldType onlyStoredType = new FieldType(); onlyStoredType.setTokenized(false); onlyStoredType.setIndexOptions(IndexOptions.NONE); onlyStoredType.setStored(true); onlyStoredType.freeze(); doc.add(new Field("prodId", prodId, onlyStoredType)); // 商品名稱:字符串,分詞索引(存儲詞頻、位置、偏移量)、存儲 String name = "ThinkPad X1 Carbon 20KH0009CD/25CD 超極本輕薄筆記本電腦聯想"; FieldType indexedAllStoredType = new FieldType(); indexedAllStoredType.setStored(true); indexedAllStoredType.setTokenized(true); indexedAllStoredType.setIndexOptions( IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS); indexedAllStoredType.freeze(); doc.add(new Field("name", name, indexedAllStoredType)); // 圖片連接:僅存儲 String imgUrl = "http://www.cnblogs.com/leeSmall/"; doc.add(new Field("imgUrl", imgUrl, onlyStoredType)); // 商品簡介:文本,分詞索引(不須要支持短語、臨近查詢)、存儲,結果中支持高亮顯示 String simpleIntro = "集成顯卡 英特爾 酷睿 i5-8250U 14英寸"; FieldType indexedTermVectorsStoredType = new FieldType(); indexedTermVectorsStoredType.setStored(true); indexedTermVectorsStoredType.setTokenized(true); indexedTermVectorsStoredType .setIndexOptions(IndexOptions.DOCS_AND_FREQS); indexedTermVectorsStoredType.setStoreTermVectors(true); indexedTermVectorsStoredType.setStoreTermVectorPositions(true); indexedTermVectorsStoredType.setStoreTermVectorOffsets(true); indexedTermVectorsStoredType.freeze(); doc.add(new Field("simpleIntro", simpleIntro, indexedTermVectorsStoredType)); // 價格,整數,單位分,不索引、存儲 int price = 2999900; // Field 類有整數類型值的構造方法嗎? // 用字節數組來存儲試試,仍是轉爲字符串? byte[] result = new byte[Integer.BYTES]; NumericUtils.intToSortableBytes(price, result, 0); doc.add(new Field("price", result, onlyStoredType)); writer.addDocument(doc); } catch (IOException e) { e.printStackTrace(); } } }
問題7 :咱們每每須要對搜索的結果支持按不一樣的字段進行排序,如商品搜索結果按價格排序、按銷量排序等。以及對搜索結果進行按某字段分組統計,如按品牌統計。
存儲的文檔數據中(文檔是行式存儲) 就得把搜到的全部文檔加載到內存中,來獲取價格,再按價格排序。 若是搜到的文檔列表量很大,會有什麼問題沒? 費內存 效率低 咱們每每對結果列表是分頁處理,並不須要把全部文檔數據加載。
空間換時間:對這種須要排序、分組、聚合的字段,爲其創建獨立的文檔->字段值的正向索引、列式存儲。這樣咱們要加載搜中文檔的這個字段的數據就快不少,耗內存少。
IndexableFieldType 中的 docValuesType方法 就是讓你來爲須要排序、分組、聚合的字段指定如何爲該字段建立文檔->字段值的正向索引的。
DocValuesType 選項說明:
NONE 不開啓docvalue
NUMERIC 單值、數值字段,用這個
BINARY 單值、字節數組字段用
SORTED 單值、字符字段用, 會預先對值字節進行排序、去重存儲
SORTED_NUMERIC 單值、數值數組字段用,會預先對數值數組進行排序
SORTED_SET 多值字段用,會預先對值字節進行排序、去重存儲
具體使用選擇:
字符串+單值 會選擇SORTED做爲docvalue存儲
字符串+多值 會選擇SORTED_SET做爲docvalue存儲
數值或日期或枚舉字段+單值 會選擇NUMERIC做爲docvalue存儲
數值或日期或枚舉字段+多值 會選擇SORTED_SET做爲docvalue存儲
注意:須要排序、分組、聚合、分類查詢(面查詢)的字段才建立docValues
8. 擴展整型Field
經過查看Filed的構造方法,發現裏面沒有設置整型數值的方法,因此須要咱們本身來擴展
擴展的方法以下:
1. 擴展Field,提供構造方法傳入數值類型值,賦給字段值字段;
2. 改寫binaryValue() 方法,返回數值的字節引用。
package com.study.lucene.indexdetail.extendfield; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.NumericUtils; /** * * @Description: 擴展整型Field * @author liguangsheng * @date 2018年5月11日 * */ public class ExtendIntField extends Field { public ExtendIntField(String fieldName, int value, FieldType type) { super(fieldName, type); this.fieldsData = Integer.valueOf(value); } @Override public BytesRef binaryValue() { byte[] bs = new byte[Integer.BYTES]; NumericUtils.intToSortableBytes((Integer) this.fieldsData, bs, 0); return new BytesRef(bs); } }
9. Lucene預約義的字段子類
package com.study.lucene.indexdetail; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.Field.Store; import org.apache.lucene.document.FieldType; import org.apache.lucene.document.NumericDocValuesField; import org.apache.lucene.document.SortedDocValuesField; import org.apache.lucene.document.StringField; import org.apache.lucene.index.DocValuesType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.BytesRef; import org.apache.lucene.util.NumericUtils; import com.study.lucene.ikanalyzer.Integrated.IKAnalyzer4Lucene7; /** * 索引的建立 * * @author THINKPAD * */ public class IndexWriteDemo { public static void main(String[] args) { // 建立使用的分詞器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); // 索引配置對象 IndexWriterConfig config = new IndexWriterConfig(analyzer); try ( // 索引存放目錄 // 存放到文件系統中 Directory directory = FSDirectory.open((new File("f:/test/indextest")).toPath()); // 存放到內存中 // Directory directory = new RAMDirectory(); // 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config);) { // 準備document Document doc = new Document(); // 商品id:字符串,不索引、但存儲 String prodId = "p0001"; FieldType onlyStoredType = new FieldType(); onlyStoredType.setTokenized(false); onlyStoredType.setIndexOptions(IndexOptions.NONE); onlyStoredType.setStored(true); onlyStoredType.freeze(); doc.add(new Field("prodId", prodId, onlyStoredType)); // 等同下一行 // doc.add(new StoredField("prodId", prodId)); // 商品名稱:字符串,分詞索引(存儲詞頻、位置、偏移量)、存儲 String name = "ThinkPad X1 Carbon 20KH0009CD/25CD 超極本輕薄筆記本電腦聯想"; FieldType indexedAllStoredType = new FieldType(); indexedAllStoredType.setStored(true); indexedAllStoredType.setTokenized(true); indexedAllStoredType.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS); indexedAllStoredType.freeze(); doc.add(new Field("name", name, indexedAllStoredType)); // 圖片連接:僅存儲 String imgUrl = "http://www.cnblogs.com/aaa"; doc.add(new Field("imgUrl", imgUrl, onlyStoredType)); // 商品簡介:文本,分詞索引(不須要支持短語、臨近查詢)、存儲,結果中支持高亮顯示 String simpleIntro = "集成顯卡 英特爾 酷睿 i5-8250U 14英寸"; FieldType indexedTermVectorsStoredType = new FieldType(); indexedTermVectorsStoredType.setStored(true); indexedTermVectorsStoredType.setTokenized(true); indexedTermVectorsStoredType.setIndexOptions(IndexOptions.DOCS_AND_FREQS); indexedTermVectorsStoredType.setStoreTermVectors(true); indexedTermVectorsStoredType.setStoreTermVectorPositions(true); indexedTermVectorsStoredType.setStoreTermVectorOffsets(true); indexedTermVectorsStoredType.freeze(); doc.add(new Field("simpleIntro", simpleIntro, indexedTermVectorsStoredType)); // 價格,整數,單位分,不索引、存儲、要支持排序 int price = 999900; FieldType numericDocValuesType = new FieldType(); numericDocValuesType.setTokenized(false); numericDocValuesType.setIndexOptions(IndexOptions.NONE); numericDocValuesType.setStored(true); numericDocValuesType.setDocValuesType(DocValuesType.NUMERIC); numericDocValuesType.setDimensions(1, Integer.BYTES); numericDocValuesType.freeze(); doc.add(new MyIntField("price", price, numericDocValuesType)); // 與下兩行等同 // doc.add(new StoredField("price", price)); // doc.add(new NumericDocValuesField("price", price)); // 類別:字符串,索引不分詞,不存儲、支持分類統計,多值 FieldType indexedDocValuesType = new FieldType(); indexedDocValuesType.setTokenized(false); indexedDocValuesType.setIndexOptions(IndexOptions.DOCS); indexedDocValuesType.setDocValuesType(DocValuesType.SORTED_SET); indexedDocValuesType.freeze(); doc.add(new Field("type", "電腦", indexedDocValuesType) { @Override public BytesRef binaryValue() { return new BytesRef((String) this.fieldsData); } }); doc.add(new Field("type", "筆記本電腦", indexedDocValuesType) { @Override public BytesRef binaryValue() { return new BytesRef((String) this.fieldsData); } }); // 等同下四行 // doc.add(new StringField("type", "電腦", Store.NO)); // doc.add(new SortedSetDocValuesField("type", new BytesRef("電腦"))); // doc.add(new StringField("type", "筆記本電腦", Store.NO)); // doc.add(new SortedSetDocValuesField("type", new // BytesRef("筆記本電腦"))); // 商家 索引(不分詞),存儲、按面(分類)查詢 String fieldName = "shop"; String value = "聯想官方旗艦店"; doc.add(new StringField(fieldName, value, Store.YES)); doc.add(new SortedDocValuesField(fieldName, new BytesRef(value))); // 上架時間:數值,排序須要 long upShelfTime = System.currentTimeMillis(); doc.add(new NumericDocValuesField("upShelfTime", upShelfTime)); writer.addDocument(doc); } catch (IOException e) { e.printStackTrace(); } } public static class MyIntField extends Field { public MyIntField(String fieldName, int value, FieldType type) { super(fieldName, type); this.fieldsData = Integer.valueOf(value); } @Override public BytesRef binaryValue() { byte[] bs = new byte[Integer.BYTES]; NumericUtils.intToSortableBytes((Integer) this.fieldsData, bs, 0); return new BytesRef(bs); } } }
IndexWriter 索引更新 API
說明:
Term 詞項 指定字段的詞項
刪除流程:根據Term、Query找到相關的文檔id、同時刪除索引信息,再根據文檔id刪除對應的文檔存儲。
更新流程:先刪除、再加入新的doc
注意:只可根據索引的字段進行更新。
package com.study.lucene.indexdetail; import java.io.File; import java.io.IOException; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.FieldType; import org.apache.lucene.index.IndexOptions; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.index.Term; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import com.study.lucene.ikanalyzer.Integrated.IKAnalyzer4Lucene7; /** * @Description: 索引更新 * @author liguangsheng * @date 2018年5月11日 * */ public class IndexUpdateDemo { public static void main(String[] args) { // 建立使用的分詞器 Analyzer analyzer = new IKAnalyzer4Lucene7(true); // 索引配置對象 IndexWriterConfig config = new IndexWriterConfig(analyzer); try ( // 索引存放目錄 // 存放到文件系統中 Directory directory = FSDirectory.open((new File("f:/test/indextest")).toPath()); // 存放到內存中 // Directory directory = new RAMDirectory(); // 建立索引寫對象 IndexWriter writer = new IndexWriter(directory, config);) { // Term term = new Term("prodId", "p0001"); Term term = new Term("type", "筆記本電腦"); // 準備document Document doc = new Document(); // 商品id:字符串,不索引、但存儲 String prodId = "p0003"; FieldType onlyStoredType = new FieldType(); onlyStoredType.setTokenized(false); onlyStoredType.setIndexOptions(IndexOptions.NONE); onlyStoredType.setStored(true); onlyStoredType.freeze(); doc.add(new Field("prodId", prodId, onlyStoredType)); writer.updateDocument(term, doc); // Term term = new Term("name", "筆記本電腦"); // writer.deleteDocuments(term); writer.flush(); writer.commit(); System.out.println("執行更新完畢。"); } catch (IOException e) { e.printStackTrace(); } } }
源碼獲取地址:
https://github.com/leeSmall/SearchEngineDemo