lucene 第一天
?
?
?
Lucene/Solr
?
第一天
?
1.?課程計劃
a)?索引流程
b)?搜索流程
a)?索引實現
b)?搜索實現
a)?分詞介紹
b)?IK分詞器
?
?
?
?
?
2.?搜索介紹
2.1.?實現搜索的方案
原來的方式實現搜索功能,我們的搜索流程如下圖:
?
上圖就是原始搜索引擎技術,如果用戶比較少而且數據庫的數據量比較小,那么這種方式實現搜索功能在企業中是比較常見的。
?
但是數據量過多時,數據庫的壓力就會變得很大,查詢速度會變得非常慢。我們需要使用更好的解決方案來分擔數據庫的壓力。
?
現在的方案(使用Lucene),如下圖
?
為了解決數據庫壓力和速度的問題,我們的數據庫就變成了索引庫,我們使用Lucene的API的來操作服務器上的索引庫。這樣完全和數據庫進行了隔離。
?
?
?
2.2.?數據查詢方法
2.2.1.?順序掃描法
所謂順序掃描,例如要找內容包含一個字符串的文件,就是一個文檔一個文檔的看,對于每一個文檔,從頭看到尾,如果此文檔包含此字符串,則此文檔為我們要找的文件,接著看下一個文件,直到掃描完所有的文件。
這種方法是順序掃描方法,數據量大就搜索慢。
?
2.2.2.?倒排索引
先舉一個栗子:
例如我們使用新華字典查詢漢字,新華字典有偏旁部首的目錄(索引),我們查字首先查這個目錄,找到這個目錄中對應的偏旁部首,就可以通過這個目錄中的偏旁部首找到這個字所在的位置(文檔)。
?
?
現在有兩篇文檔:
Doc1: When in Rome, do as the Romans do.
Doc2: When do you come back from Rome?
?
Lucene會對以上兩篇文檔建立倒排索引
索引結構如下圖:
?
1、?提取資源中關鍵信息, 建立索引 (目錄)
2、?搜索時,根據關鍵字(目錄),找到資源的位置
?
?
1.1.?搜索技術應用場景
應用場景 :
1、 單機軟件的搜索(word中的搜索)
2、 站內搜索 (baidu貼吧、論壇、 京東、 taobao)
3、 垂直領域的搜索 (818工作網)
4、 專業搜索引擎公司 (google、baidu)
?
?
?
?
?
?
?
?
?
?
?
3.?Lucene介紹
3.1.?什么是全文索引
計算機索引程序通過掃描文章中的每一個詞,對每一個詞建立一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先建立的索引進行查找,并將查找的結果反饋給用戶的檢索方式
?
3.2.?什么是Lucene
Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,但它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。
?
Lucene的目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。
?
目前已經有很多應用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的幫助系統的搜索功能。Lucene 能夠為文本類型的數據建立索引,所以你只要能把你要索引的數據格式轉化的文本的,Lucene 就能對你的文檔進行索引和搜索。比如你要對一些 HTML 文檔,PDF 文檔進行索引的話你就首先需要把 HTML 文檔和 PDF 文檔轉化成文本格式的,然后將轉化后的內容交給 Lucene 進行索引,然后把創建好的索引文件保存到磁盤或者內存中,最后根據用戶輸入的查詢條件在索引文件上進行查詢。不指定要索引的文檔的格式也使 Lucene 能夠幾乎適用于所有的搜索應用程序。
?
l?Lucene是一套用于全文檢索和搜尋的開源程式庫,由Apache軟件基金會支 持和提供
l?Lucene提供了一個簡單卻強大的應用程式接口,能夠做全文索引和搜尋, 在Java開發環境里Lucene是一個成熟的免費開放源代碼工具
l?Lucene并不是現成的搜索引擎產品,但可以用來制作搜索引擎產品
?
?
3.3.?Lucene與搜索引擎的區別
全文檢索系統是按照全文檢索理論建立起來的用于提供全文檢索服務的軟件系統,包括建立索引、處理查詢返回結果集、增加索引、優化索引結構等功能。例如:百度搜索、eclipse幫助搜索、淘寶網商品搜索等。
?
搜索引擎是全文檢索技術最主要的一個應用,例如百度。搜索引擎起源于傳統的信息全文檢索理論,即計算機程序通過掃描每一篇文章中的每一個詞,建立以詞為單位的倒排文件,檢索程序根據檢索詞在每一篇文章中出現的頻率和每一個檢索詞在一篇文章中出現的概率,對包含這些檢索詞的文章進行排序,最后輸出排序的結果。全文檢索技術是搜索引擎的核心支撐技術。
?
Lucene和搜索引擎不同,Lucene是一套用java或其它語言寫的全文檢索的工具包,為應用程序提供了很多個api接口去調用,可以簡單理解為是一套實現全文檢索的類庫,搜索引擎是一個全文檢索系統,它是一個單獨運行的軟件系統
?
3.4.?Lucene官網
官網: http://lucene.apache.org/?
?
4.?Lucene全文檢索的流程
4.1.?索引和搜索流程圖
?
?
1、綠色表示索引過程,對要搜索的原始內容進行索引構建一個索引庫,索引過程包括:
確定原始內容即要搜索的內容à獲得文檔à創建文檔à分析文檔à索引文檔
?
2、紅色表示搜索過程,從索引庫中搜索內容,搜索過程包括:
用戶通過搜索界面à創建查詢à執行搜索,從索引庫搜索à渲染搜索結果
4.2.?索引流程
對文檔索引的過程,將用戶要搜索的文檔內容進行索引,索引存儲在索引庫(index)中。
?
4.2.1.?原始內容
原始內容是指要索引和搜索的內容。
原始內容包括互聯網上的網頁、數據庫中的數據、磁盤上的文件等。
?
4.2.2.?獲得文檔(采集數據)
從互聯網上、數據庫、文件系統中等獲取需要搜索的原始信息,這個過程就是信息采集,采集數據的目的是為了對原始內容進行索引。
?
采集數據分類:
1、對于互聯網上網頁,可以使用工具將網頁抓取到本地生成html文件。
2、數據庫中的數據,可以直接連接數據庫讀取表中的數據。
3、文件系統中的某個文件,可以通過I/O操作讀取文件的內容。
?
在Internet上采集信息的軟件通常稱為爬蟲或蜘蛛,也稱為網絡機器人,爬蟲訪問互聯網上的每一個網頁,將獲取到的網頁內容存儲起來。
Lucene不提供信息采集的類庫,需要自己編寫一個爬蟲程序實現信息采集,也可以通過一些開源軟件實現信息采集,如下:
Solr(http://lucene.apache.org/solr) ,solr是apache的一個子項目,支持從關系數據庫、xml文檔中提取原始數據。
Nutch(http://lucene.apache.org/nutch), Nutch是apache的一個子項目,包括大規模爬蟲工具,能夠抓取和分辨web網站數據。
jsoup(http://jsoup.org/?),jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數據。
?
4.2.3.?創建文檔
獲取原始內容的目的是為了索引,在索引前需要將原始內容創建成文檔(Document),文檔中包括一個一個的域(Field),域中存儲內容。
這里我們可以將磁盤上的一個文件當成一個document,Document中包括一些Field,如下圖:
?
?
注意:每個Document可以有多個Field,不同的Document可以有不同的Field,同一個Document可以有相同的Field(域名和域值都相同)
4.2.4.?分析文檔
將原始內容創建為包含域(Field)的文檔(document),需要再對域中的內容進行分析,分析成為一個一個的單詞。
?
比如下邊的文檔經過分析如下:
原文檔內容:
Lucene is a Java full-text search engine. ?Lucene is not a complete
application, but rather a code library and API that can easily be used
to add search capabilities to applications.
?
分析后得到的詞:
lucene、java、full、search、engine。。。。
?
4.2.5.?索引文檔
對所有文檔分析得出的語匯單元進行索引,索引的目的是為了搜索,最終要實現只搜索被索引的語匯單元從而找到Document(文檔)。
?
創建索引是對語匯單元索引,通過詞語找文檔,這種索引的結構叫倒排索引結構。
?
倒排索引結構是根據內容(詞匯)找文檔,如下圖:
?
?
?
倒排索引結構也叫反向索引結構,包括索引和文檔兩部分,索引即詞匯表,它的規模較小,而文檔集合較大。
?
4.3.?搜索流程
搜索就是用戶輸入關鍵字,從索引中進行搜索的過程。根據關鍵字搜索索引,根據索引找到對應的文檔,從而找到要搜索的內容。
?
4.3.1.?用戶
就是使用搜索的角色,用戶可以是自然人,也可以是遠程調用的程序。
?
4.3.2.?用戶搜索界面
全文檢索系統提供用戶搜索的界面供用戶提交搜索的關鍵字,搜索完成展示搜索結果。如下圖:
?
Lucene不提供制作用戶搜索界面的功能,需要根據自己的需求開發搜索界面。
?
4.3.3.?創建查詢
用戶輸入查詢關鍵字執行搜索之前需要先構建一個查詢對象,查詢對象中可以指定查詢要查詢關鍵字、要搜索的Field文檔域等,查詢對象會生成具體的查詢語法,比如:
name:lucene表示要搜索name這個Field域中,內容為“lucene”的文檔。
desc:lucene AND desc:java 表示要搜索既包括關鍵字“lucene”也包括“java”的文檔。
?
4.3.4.?執行搜索
搜索索引過程:
1.根據查詢語法在倒排索引詞典表中分別找出對應搜索詞的索引,從而找到索引所鏈接的文檔鏈表。
例如搜索語法為“desc:lucene AND desc:java”表示搜索出的文檔中既要包括lucene也要包括java。
?
?
2、由于是AND,所以要對包含lucene或java詞語的鏈表進行交集,得到文檔鏈表應該包括每一個搜索詞語
?
3、獲取文檔中的Field域數據。
?
4.3.5.?渲染結果
以一個友好的界面將查詢結果展示給用戶,用戶根據搜索結果找自己想要的信息,為了幫助用戶很快找到自己的結果,提供了很多展示的效果,比如搜索結果中將關鍵字高亮顯示,百度提供的快照等。
?
5.?Lucene入門
5.1.?Lucene準備
Lucene可以在官網上下載。課程已經準備好了Lucene的文件,我們使用的是4.10.3版本,文件位置如下圖:
?
解壓后的效果:
?
使用這三個文件的jar包,就可以實現lucene功能
?
本教程使用的數據是MySQL數據庫的數據,所以還需要MySQL的連接包
學員編寫的時候,也可以直接復制準備好的jar包,位置如下圖:
?
5.2.?開發環境
JDK: 1.7 (Lucene4.8以上,必須使用JDK1.7及以上版本)
IDE: eclipse Mars2
數據庫: MySQL
?
數據庫腳本位置如下圖:
?
?
?
導入到MySQL效果如下圖:
?
?
5.3.?創建Java工程
創建java工程測試即可,效果如下:
?
?
?
5.4.?索引流程
5.4.1.?數據采集
在電商網站中,全文檢索的數據源在數據庫中,需要通過jdbc訪問數據庫中book表的內容。
5.4.1.1.?創建pojo
public?class?Book {
// 圖書ID
private?Integer id;
// 圖書名稱
private?String name;
// 圖書價格
private?Float price;
// 圖書圖片
private?String pic;
// 圖書描述
private?String desc;
get/set。。。
}
?
5.4.1.2.?創建DAO接口
public?interface?BookDao {
?
/**
?* 查詢所有的book數據
?*
?* @return
?*/
List<Book> queryBookList();
}
?
5.4.1.3.?創建DAO接口實現類
使用jdbc實現
public?class?BookDaoImpl implements?BookDao {
?
@Override
public?List<Book> queryBookList() {
// 數據庫鏈接
Connection connection?= null;
// 預編譯statement
PreparedStatement preparedStatement?= null;
// 結果集
ResultSet resultSet?= null;
// 圖書列表
List<Book> list?= new?ArrayList<Book>();
?
try?{
// 加載數據庫驅動
Class.forName("com.mysql.jdbc.Driver");
// 連接數據庫
connection?= DriverManager.getConnection("jdbc:mysql://localhost:3306/solr", "root", "root");
?
// SQL語句
String sql?= "SELECT * FROM book";
// 創建preparedStatement
preparedStatement?= connection.prepareStatement(sql);
// 獲取結果集
resultSet?= preparedStatement.executeQuery();
// 結果集解析
while?(resultSet.next()) {
Book book?= new?Book();
book.setId(resultSet.getInt("id"));
book.setName(resultSet.getString("name"));
book.setPrice(resultSet.getFloat("price"));
book.setPic(resultSet.getString("pic"));
book.setDesc(resultSet.getString("desc"));
list.add(book);
}
} catch?(Exception e) {
e.printStackTrace();
}
?
return?list;
}
}
?
5.4.2.?實現索引流程
public?class?CreateIndexTest {
@Test
public?void?testCreateIndex() throws?Exception {
// 1. 采集數據
BookDao bookDao?= new?BookDaoImpl();
List<Book> bookList?= bookDao.queryBookList();
?
// 2. 創建Document文檔對象
List<Document> documents?= new?ArrayList<>();
for?(Book book?: bookList) {
Document document?= new?Document();
?
// Document文檔中添加Field域
// 圖書Id
// Store.YES:表示存儲到文檔域中
document.add(new?TextField("id", book.getId().toString(), Store.YES));
// 圖書名稱
document.add(new?TextField("name", book.getName().toString(), Store.YES));
// 圖書價格
document.add(new?TextField("price", book.getPrice().toString(), Store.YES));
// 圖書圖片地址
document.add(new?TextField("pic", book.getPic().toString(), Store.YES));
// 圖書描述
document.add(new?TextField("desc", book.getDesc().toString(), Store.YES));
?
// 把Document放到list中
documents.add(document);
}
?
// 3. 創建Analyzer分詞器,分析文檔,對文檔進行分詞
Analyzer analyzer?= new?StandardAnalyzer();
?
// 4. 創建Directory對象,聲明索引庫的位置
Directory directory?= FSDirectory.open(new?File("C:/itcast/lucene/index"));
?
// 5. 創建IndexWriteConfig對象,寫入索引需要的配置
IndexWriterConfig config?= new?IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
?
// 6.創建IndexWriter寫入對象
IndexWriter indexWriter?= new?IndexWriter(directory, config);
?
// 7.寫入到索引庫,通過IndexWriter添加文檔對象document
for?(Document doc?: documents) {
indexWriter.addDocument(doc);
}
?
// 8.釋放資源
indexWriter.close();
}
}
?
執行效果:
在文件夾中出現了以下文件,表示創建索引成功
?
?
?
5.4.3.?使用Luke查看索引
Luke作為Lucene工具包中的一個工具(http://www.getopt.org/luke/),可以通過界面來進行索引文件的查詢、修改
luke所在位置如下圖:
?
?
?
打開Luke方法:打開cmd命令行運行命令:java -jar lukeall-4.10.3.jar
打開后,使用如下圖:
?
?
下圖是索引域的展示效果:
?
?
下圖是文檔域展示效果
?
?
?
5.5.?搜索流程
5.5.1.?輸入查詢語句
Lucene可以通過query對象輸入查詢語句。同數據庫的sql一樣,lucene也有固定的查詢語法:
最基本的有比如:AND, OR, NOT 等(必須大寫)
?
舉個栗子:
用戶想找一個desc中包括java關鍵字和lucene關鍵字的文檔。
它對應的查詢語句:desc:java?AND desc:lucene
?
?
?
?
?
?
?
?
如下圖是使用luke搜索的例子:
?
?
?
5.5.1.1.?搜索分詞
和索引過程的分詞一樣,這里要對用戶輸入的關鍵字進行分詞,一般情況索引和搜索使用的分詞器一致。
比如:輸入搜索關鍵字“java學習”,分詞后為java和學習兩個詞,與java和學習有關的內容都搜索出來了,如下:
?
?
?
5.5.2.?代碼實現
?1. 創建Query搜索對象
?2. 創建Directory流對象,聲明索引庫位置
?3. 創建索引讀取對象IndexReader
?4. 創建索引搜索對象IndexSearcher
?5. 使用索引搜索對象,執行搜索,返回結果集TopDocs
?6. 解析結果集
?7. 釋放資源
?
IndexSearcher搜索方法如下:
| 方法 | 說明 |
| indexSearcher.search(query, n) | 根據Query搜索,返回評分最高的n條記錄 |
| indexSearcher.search(query, filter, n) | 根據Query搜索,添加過濾策略,返回評分最高的n條記錄 |
| indexSearcher.search(query, n, sort) | 根據Query搜索,添加排序策略,返回評分最高的n條記錄 |
| indexSearcher.search(booleanQuery, filter, n, sort) | 根據Query搜索,添加過濾策略,添加排序策略,返回評分最高的n條記錄 |
?
代碼實現
public?class?SearchIndexTest {
@Test
public?void?testSearchIndex() throws?Exception {
// 1. 創建Query搜索對象
// 創建分詞器
Analyzer analyzer?= new?StandardAnalyzer();
// 創建搜索解析器,第一個參數:默認Field域,第二個參數:分詞器
QueryParser queryParser?= new?QueryParser("desc", analyzer);
?
// 創建搜索對象
Query query?= queryParser.parse("desc:java AND lucene");
?
// 2. 創建Directory流對象,聲明索引庫位置
Directory directory?= FSDirectory.open(new?File("C:/itcast/lucene/index"));
?
// 3. 創建索引讀取對象IndexReader
IndexReader reader?= DirectoryReader.open(directory);
?
// 4. 創建索引搜索對象
IndexSearcher searcher?= new?IndexSearcher(reader);
?
// 5. 使用索引搜索對象,執行搜索,返回結果集TopDocs
// 第一個參數:搜索對象,第二個參數:返回的數據條數,指定查詢結果最頂部的n條數據返回
TopDocs topDocs?= searcher.search(query, 10);
System.out.println("查詢到的數據總條數是:"?+ topDocs.totalHits);
// 獲取查詢結果集
ScoreDoc[] docs?= topDocs.scoreDocs;
?
// 6. 解析結果集
for?(ScoreDoc scoreDoc?: docs) {
// 獲取文檔
int?docID?= scoreDoc.doc;
Document doc?= searcher.doc(docID);
?
System.out.println("=============================");
System.out.println("docID:"?+ docID);
System.out.println("bookId:"?+ doc.get("id"));
System.out.println("name:"?+ doc.get("name"));
System.out.println("price:"?+ doc.get("price"));
System.out.println("pic:"?+ doc.get("pic"));
// System.out.println("desc:" + doc.get("desc"));
}
// 7. 釋放資源
reader.close();
}
}
?
?
?
?
?
6.?分詞器
6.1.?分詞理解
在對Docuemnt中的內容進行索引之前,需要使用分詞器進行分詞 ,分詞的目的是為了搜索。分詞的主要過程就是先分詞后過濾。
?
l?分詞:采集到的數據會存儲到document對象的Field域中,分詞就是將Document中Field的value值切分成一個一個的詞。
l?過濾:包括去除標點符號過濾、去除停用詞過濾(的、是、a、an、the等)、大寫轉小寫、詞的形還原(復數形式轉成單數形參、過去式轉成現在式。。。)等。?
?
什么是停用詞?停用詞是為節省存儲空間和提高搜索效率,搜索引擎在索引頁面或處理搜索請求時會自動忽略某些字或詞,這些字或詞即被稱為Stop Words(停用詞)。比如語氣助詞、副詞、介詞、連接詞等,通常自身并無明確的意義,只有將其放入一個完整的句子中才有一定作用,如常見的“的”、“在”、“是”、“啊”等。
?
對于分詞來說,不同的語言,分詞規則不同。Lucene作為一個工具包提供不同國家的分詞器,本例子使用StandardAnalyzer,它可以對用英文進行分詞。
?
如下是org.apache.lucene.analysis.standard.standardAnalyzer的部分源碼:
??@Override
??protected?TokenStreamComponents createComponents(final?String fieldName, final?Reader?reader) {
????final?StandardTokenizer?src?= new?StandardTokenizer(getVersion(), reader);
????src.setMaxTokenLength(maxTokenLength);
????TokenStream tok?= new?StandardFilter(getVersion(), src);
????tok?= new?LowerCaseFilter(getVersion(), tok);
????tok?= new?StopFilter(getVersion(), tok, stopwords);
????return?new?TokenStreamComponents(src, tok) {
??????@Override
??????protected?void?setReader(final?Reader reader) throws?IOException {
????????src.setMaxTokenLength(StandardAnalyzer.this.maxTokenLength);
????????super.setReader(reader);
??????}
????};
??}
?
Tokenizer就是分詞器,負責將reader轉換為語匯單元即進行分詞處理,Lucene提供了很多的分詞器,也可以使用第三方的分詞,比如IKAnalyzer一個中文分詞器。
?
TokenFilter是分詞過濾器,負責對語匯單元進行過濾,TokenFilter可以是一個過濾器鏈兒,Lucene提供了很多的分詞器過濾器,比如大小寫轉換、去除停用詞等。
?
如下圖是語匯單元的生成過程:
?
?
?
從一個Reader字符流開始,創建一個基于Reader的Tokenizer分詞器,經過三個TokenFilter生成語匯單元Token。
?
比如下邊的文檔經過分析器分析如下:
- 原文檔內容:
?
?
?
?
- 分析后得到的多個語匯單元:
?
?
?
?
?
6.2.?Analyzer使用時機
6.2.1.?索引時使用Analyzer
輸入關鍵字進行搜索,當需要讓該關鍵字與文檔域內容所包含的詞進行匹配時需要對文檔域內容進行分析,需要經過Analyzer分析器處理生成語匯單元(Token)。分析器分析的對象是文檔中的Field域。當Field的屬性tokenized(是否分詞)為true時會對Field值進行分析,如下圖:
?
?
?
對于一些Field可以不用分析:
1、不作為查詢條件的內容,比如文件路徑
2、不是匹配內容中的詞而匹配Field的整體內容,比如訂單號、身份證號等。
?
?
6.2.2.?搜索時使用Analyzer
對搜索關鍵字進行分析和索引分析一樣,使用Analyzer對搜索關鍵字進行分析、分詞處理,使用分析后每個詞語進行搜索。比如:搜索關鍵字:spring web ,經過分析器進行分詞,得出:spring??web拿詞去索引詞典表查找 ,找到索引鏈接到Document,解析Document內容。
對于匹配整體Field域的查詢可以在搜索時不分析,比如根據訂單號、身份證號查詢等。
注意:搜索使用的分析器要和索引使用的分析器一致。
?
6.3.?中文分詞器
6.3.1.?什么是中文分詞器
學過英文的都知道,英文是以單詞為單位的,單詞與單詞之間以空格或者逗號句號隔開。所以對于英文,我們可以簡單以空格判斷某個字符串是否為一個單詞,比如I love China,love 和 China很容易被程序區分開來。
?
而中文則以字為單位,字又組成詞,字和詞再組成句子。中文“我愛中國”就不一樣了,電腦不知道“中國”是一個詞語還是“愛中”是一個詞語。
?
把中文的句子切分成有意義的詞,就是中文分詞,也稱切詞。我愛中國,分詞的結果是:我、愛、中國。
?
6.3.2.?Lucene自帶中文分詞器
l?StandardAnalyzer:
單字分詞:就是按照中文一個字一個字地進行分詞。如:“我愛中國”,
效果:“我”、“愛”、“中”、“國”。
?
l?CJKAnalyzer
二分法分詞:按兩個字進行切分。如:“我是中國人”,效果:“我是”、“是中”、“中國”“國人”。
?
上邊兩個分詞器無法滿足需求。
l?SmartChineseAnalyzer
對中文支持較好,但擴展性差,擴展詞庫,禁用詞庫和同義詞庫等不好處理
?
6.4.?第三方中文分詞器
l?paoding: 庖丁解牛最新版在?https://code.google.com/p/paoding/?中最多支持Lucene 3.0,且最新提交的代碼在 2008-06-03,在svn中最新也是2010年提交,已經過時,不予考慮。
?
l?mmseg4j:最新版已從?https://code.google.com/p/mmseg4j/?移至?https://github.com/chenlb/mmseg4j-solr,支持Lucene 4.10,且在github中最新提交代碼是2014年6月,從09年~14年一共有:18個版本,也就是一年幾乎有3個大小版本,有較大的活躍度,用了mmseg算法。
?
l?IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10從2006年12月推出1.0版開始, IKAnalyzer已經推出了4個大版本。最初,它是以開源項目Luence為應用主體的,結合詞典分詞和文法分析算法的中文分詞組件。從3.0版本開 始,IK發展為面向Java的公用分詞組件,獨立于Lucene項目,同時提供了對Lucene的默認優化實現。在2012版本中,IK實現了簡單的分詞 歧義排除算法,標志著IK分詞器從單純的詞典分詞向模擬語義分詞衍化。 但是也就是2012年12月后沒有在更新。
?
l?ansj_seg:最新版本在?https://github.com/NLPchina/ansj_seg?tags僅有1.1版本,從2012年到2014年更新了大小6次,但是作者本人在2014年10月10日說明:“可能我以后沒有精力來維護ansj_seg了”,現在由”nlp_china”管理。2014年11月有更新。并未說明是否支持Lucene,是一個由CRF(條件隨機場)算法所做的分詞算法。
?
l?imdict-chinese-analyzer:最新版在?https://code.google.com/p/imdict-chinese-analyzer/?, 最新更新也在2009年5月,下載源碼,不支持Lucene 4.10 。是利用HMM(隱馬爾科夫鏈)算法。
?
l?Jcseg:最新版本在git.oschina.net/lionsoul/jcseg,支持Lucene 4.10,作者有較高的活躍度。利用mmseg算法。
?
6.5.?使用中文分詞器IKAnalyzer
IKAnalyzer繼承Lucene的Analyzer抽象類,使用IKAnalyzer和Lucene自帶的分析器方法一樣,將Analyzer測試代碼改為IKAnalyzer測試中文分詞效果。
?
如果使用中文分詞器ik-analyzer,就需要在索引和搜索程序中使用一致的分詞器:IK-analyzer。
6.5.1.?添加jar包
?
?
?
6.5.2.?修改分詞器代碼
@Test
public?void?testCreateIndex() throws?Exception {
// 1. 采集數據
BookDao bookDao?= new?BookDaoImpl();
List<Book> bookList?= bookDao.queryBookList();
?
// 2. 創建Document文檔對象
List<Document> documents?= new?ArrayList<>();
for?(Book book?: bookList) {
Document document?= new?Document();
?
// Document文檔中添加Field域
// 圖書Id
// Store.YES:表示存儲到文檔域中
document.add(new?TextField("id", book.getId().toString(), Store.YES));
// 圖書名稱
document.add(new?TextField("name", book.getName().toString(), Store.YES));
// 圖書價格
document.add(new?TextField("price", book.getPrice().toString(), Store.YES));
// 圖書圖片地址
document.add(new?TextField("pic", book.getPic().toString(), Store.YES));
// 圖書描述
document.add(new?TextField("desc", book.getDesc().toString(), Store.YES));
?
// 把Document放到list中
documents.add(document);
}
?
// 3. 創建Analyzer分詞器,分析文檔,對文檔進行分詞
// Analyzer analyzer = new StandardAnalyzer();
Analyzer analyzer?= new?IKAnalyzer();
?
// 4. 創建Directory對象,聲明索引庫的位置
Directory directory?= FSDirectory.open(new?File("C:/itcast/lucene/index"));
?
// 5. 創建IndexWriteConfig對象,寫入索引需要的配置
IndexWriterConfig config?= new?IndexWriterConfig(Version.LUCENE_4_10_3, analyzer);
?
// 6.創建IndexWriter寫入對象
IndexWriter indexWriter?= new?IndexWriter(directory, config);
?
// 7.寫入到索引庫,通過IndexWriter添加文檔對象document
for?(Document doc?: documents) {
indexWriter.addDocument(doc);
}
?
// 8.釋放資源
indexWriter.close();
}
?
6.6.?擴展中文詞庫
如果想配置擴展詞和停用詞,就創建擴展詞的文件和停用詞的文件。
注意:不要用window自帶的記事本保存擴展詞文件和停用詞文件,那樣的話,格式中是含有bom的。
?
?
?
?
?
?
?
?
從ikanalyzer包中拷貝配置文件
?
?
?
拷貝到資源文件夾中
?
?
?
IKAnalyzer.cfg.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>
?
中文詞庫,添加新詞的地方
?
?
?
stopword.dic是存放停用詞的地方
?
?
?
最終分詞效果
?
轉載于:https://www.cnblogs.com/shan1393/p/9343630.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的lucene 第一天的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 对事务的特性ACID的理解
- 下一篇: 无主之地3泰瑞在哪