Lucene--Field域和索引維護
一、Field域
1.Field屬性
Field是文檔中的域渣窜,包括Field名和Field值兩部分,一個文檔可以包括多個Field,Document只是Field的一個承載體缕减,F(xiàn)ield值即為要索引的內(nèi)容,也是要搜索的內(nèi)容芒珠。
- 是否分詞(tokenized)
是:作分詞處理桥狡,即將Field值進行分詞,分詞的目的是為了索引妓局。
比如:商品名稱总放、商品簡介等,這些內(nèi)容用戶要輸入關鍵字搜索好爬,由于搜索的內(nèi)容格式大局雄、內(nèi)容多需要分詞后將語匯單元索引。
否:不作分詞處理
比如:商品id存炮、訂單號炬搭、身份證號等
- 是否索引(indexed)
是:進行索引。將Field分詞后的詞或整個Field值進行索引穆桂,索引的目的是為了搜索宫盔。
比如:商品名稱、商品簡介分析后進行索引享完,訂單號灼芭、身份證號不用分析但也要索引,這些將來都要作為查詢條件般又。
否:不索引彼绷。該域的內(nèi)容無法搜索到
比如:商品id巍佑、文件路徑、圖片路徑等寄悯,不用作為查詢條件的不用索引萤衰。
- 是否存儲(stored)
是:將Field值存儲在文檔中,存儲在文檔中的Field才可以從Document中獲取猜旬。
比如:商品名稱脆栋、訂單號,凡是將來要從Document中獲取的Field都要存儲洒擦。
否:不存儲Field值椿争,不存儲的Field無法通過Document獲取
比如:商品簡介,內(nèi)容較大不用存儲熟嫩。如果要向用戶展示商品簡介可以從系統(tǒng)的關系數(shù)據(jù)庫中獲取商品簡介丘薛。
如果需要商品描述,則根據(jù)搜索出的商品ID去數(shù)據(jù)庫中查詢邦危,然后顯示出商品描述信息即可洋侨。
2.Field常用類型
開發(fā)中常用 的Filed類型,注意Field的屬性倦蚪,根據(jù)需求選擇:
3.Field改進代碼
圖書id:
是否分詞:不用分詞希坚,因為不會根據(jù)商品id來搜索商品
是否索引:不索引蚓聘,因為不需要根據(jù)圖書ID進行搜索
是否存儲:要存儲顿苇,因為查詢結(jié)果頁面需要使用id這個值苦锨。
圖書名稱:
是否分詞:要分詞伴栓,因為要將圖書的名稱內(nèi)容分詞索引,根據(jù)關鍵搜索圖書名稱抽取的詞洲胖。
是否索引:要索引休傍。
是否存儲:要存儲搭儒。
圖書價格:
是否分詞:要分詞沪悲,lucene對數(shù)字型的值只要有搜索需求的都要分詞和索
引获洲,因為lucene對數(shù)字型的內(nèi)容要特殊分詞處理,本例子可能要根據(jù)價格范
圍搜索殿如,需要分詞和索引贡珊。
是否索引:要索引
是否存儲:要存儲
圖書圖片地址:
是否分詞:不分詞
是否索引:不索引
是否存儲:要存儲
圖書描述:
是否分詞:要分詞
是否索引:要索引
是否存儲:因為圖書描述內(nèi)容量大,不在查詢結(jié)果頁面直接顯示涉馁,不存儲门岔。
不存儲是來不在lucene的索引文件中記錄,節(jié)省lucene的索引文件空間烤送,
如果要在詳情頁面顯示描述寒随,思路:
從lucene中取出圖書的id,根據(jù)圖書的id查詢關系數(shù)據(jù)庫中book表
得到描述信息。
代碼:
@Test
public void createIndex() throws Exception {
// 采集數(shù)據(jù)
BookDao dao = new BookDaoImpl();
List<Book> list = dao.queryBooks();
// 將采集到的數(shù)據(jù)封裝到Document對象中
List<Document> docList = new ArrayList<>();
Document document;
for (Book book : list) {
document = new Document();
// store:如果是yes妻往,則說明存儲到文檔域中
// 圖書ID
// 不分詞逢防、索引、存儲 StringField
Field id = new StringField("id", book.getId().toString(), Store.YES);
// 圖書名稱
// 分詞蒲讯、索引、存儲 TextField
Field name = new TextField("name", book.getName(), Store.YES);
// 圖書價格
// 分詞灰署、索引判帮、存儲 但是是數(shù)字類型,所以使用FloatField
Field price = new FloatField("price", book.getPrice(), Store.YES);
// 圖書圖片地址
// 不分詞溉箕、不索引晦墙、存儲 StoredField
Field pic = new StoredField("pic", book.getPic());
// 圖書描述
// 分詞、索引肴茄、不存儲 TextField
Field description = new TextField("description",
book.getDescription(), Store.NO);
// 設置boost值
if (book.getId() == 4)
description.setBoost(100f);
// 將field域設置到Document對象中
document.add(id);
document.add(name);
document.add(price);
document.add(pic);
document.add(description);
docList.add(document);
}
二晌畅、索引維護
需求:
管理人員通過電商系統(tǒng)更改圖書信息,這時更新的是數(shù)據(jù)庫寡痰,如果使用lucene搜索圖書信息需要在數(shù)據(jù)庫表book信息變化時及時更新lucene索引庫抗楔。
1.添加索引
調(diào)用 indexWriter.addDocument(doc)添加索引。
@Test
public void createIndex() throws Exception {
// 采集數(shù)據(jù)
BookDao dao = new BookDaoImpl();
List<Book> list = dao.queryBooks();
// 將采集到的數(shù)據(jù)封裝到Document對象中
List<Document> docList = new ArrayList<>();
Document document;
for (Book book : list) {
document = new Document();
// store:如果是yes拦坠,則說明存儲到文檔域中
// 圖書ID
Field id = new TextField("id", book.getId().toString(), Store.YES);
// 圖書名稱
Field name = new TextField("name", book.getName(), Store.YES);
// 圖書價格
Field price = new TextField("price", book.getPrice().toString(),
Store.YES);
// 圖書圖片地址
Field pic = new TextField("pic", book.getPic(), Store.YES);
// 圖書描述
Field description = new TextField("description",
book.getDescription(), Store.YES);
// 將field域設置到Document對象中
document.add(id);
document.add(name);
document.add(price);
document.add(pic);
document.add(description);
docList.add(document);
}
// 創(chuàng)建分詞器连躏,標準分詞器
Analyzer analyzer = new StandardAnalyzer();
// 創(chuàng)建IndexWriter
IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
analyzer);
// 指定索引庫的地址
File indexFile = new File("E:\\11-index\\hm19\\");
Directory directory = FSDirectory.open(indexFile);
IndexWriter writer = new IndexWriter(directory, cfg);
// 通過IndexWriter對象將Document寫入到索引庫中
for (Document doc : docList) {
writer.addDocument(doc);
}
// 關閉writer
writer.close();
}
2.刪除索引
2.1刪除指定索引
根據(jù)Term項刪除索引,滿足條件的將全部刪除贞滨。
Term是索引域中最小的單位入热。根據(jù)條件刪除時,建議根據(jù)唯一鍵來進行刪除晓铆。在solr中就是根據(jù)ID來進行刪除和修改操作的勺良。
@Test
public void deleteIndex() throws Exception {
// 創(chuàng)建分詞器,標準分詞器
Analyzer analyzer = new StandardAnalyzer();
// 創(chuàng)建IndexWriter
IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
analyzer);
Directory directory = FSDirectory
.open(new File("E:\\11-index\\hcx\\"));
// 創(chuàng)建IndexWriter
IndexWriter writer = new IndexWriter(directory, cfg);
// Terms
writer.deleteDocuments(new Term("id", "1"));
writer.close();
}
2.2刪除全部索引(慎用)
將索引目錄的索引信息全部刪除骄噪,直接徹底刪除尚困,無法恢復。慎用链蕊!
// 刪除索引
@Test
public void deleteIndex() throws Exception {
// 1尾组、指定索引庫目錄
Directory directory = FSDirectory.open(new File("E:\\11-index\\0720"));
// 2、創(chuàng)建IndexWriterConfig
IndexWriterConfig cfg = new IndexWriterConfig(Version.LATEST,
new StandardAnalyzer());
// 3示弓、 創(chuàng)建IndexWriter
IndexWriter writer = new IndexWriter(directory, cfg);
// 4讳侨、通過IndexWriter來刪除索引
// a)、刪除全部索引
writer.deleteAll();
// 5奏属、關閉IndexWriter
writer.close();
}
建議參照關系數(shù)據(jù)庫基于主鍵刪除方式跨跨,所以在創(chuàng)建索引時需要創(chuàng)建一個主鍵Field,刪除時根據(jù)此主鍵Field刪除。
索引刪除后將放在Lucene的回收站中勇婴,Lucene3.X版本可以恢復刪除的文檔忱嘹,3.X之后無法恢復。
3.修改索引
更新索引是先刪除再添加耕渴,建議對更新需求采用此方法并且要保證對已存在的索引執(zhí)行更新拘悦,可以先查詢出來,確定更新記錄存在執(zhí)行更新操作橱脸。
@Test
public void updateIndex() throws Exception {
// 創(chuàng)建分詞器础米,標準分詞器
Analyzer analyzer = new StandardAnalyzer();
// 創(chuàng)建IndexWriter
IndexWriterConfig cfg = new IndexWriterConfig(Version.LUCENE_4_10_3,
analyzer);
Directory directory = FSDirectory
.open(new File("E:\\11-index\\hcx\\"));
// 創(chuàng)建IndexWriter
IndexWriter writer = new IndexWriter(directory, cfg);
// 第一個參數(shù):指定查詢條件
// 第二個參數(shù):修改之后的對象
// 修改時如果根據(jù)查詢條件,可以查詢出結(jié)果添诉,則將以前的刪掉屁桑,然后覆蓋新的Document對象,如果沒有查詢出結(jié)果栏赴,則新增一個Document
// 修改流程即:先查詢蘑斧,再刪除,在添加
Document doc = new Document();
doc.add(new TextField("name", "lisi", Store.YES));
writer.updateDocument(new Term("name", "zhangsan"), doc);
writer.close();
}