版權(quán)所有:
(xiaodaoxiaodao)
藍(lán)小刀
?
?
xiaodaoxiaodao@gmail.com
http://www.tkk7.com/xiaodaoxiaodao/articles/103447.html
轉(zhuǎn)載請(qǐng)注明來(lái)源
/
作者
?
關(guān)于
lucene2.0
的創(chuàng)建、檢索和刪除功能的完整實(shí)現(xiàn)
?
最近要做一個(gè)站內(nèi)的全文檢索功能,主要是針對(duì)
clob
字段的,于是去網(wǎng)上找了點(diǎn)
lucene
的資料,現(xiàn)在新版本的是
2.0.0
,網(wǎng)上的例子多是
1.4.3
的,有些方法已經(jīng)廢棄了,搞了
n
久終于把
2.0.0
的功能實(shí)現(xiàn)了,呵呵,下面把實(shí)現(xiàn)的代碼貼出來(lái),實(shí)現(xiàn)了索引的創(chuàng)建、檢索和刪除功能,并可以從檢索結(jié)果去查詢(xún)數(shù)據(jù)庫(kù)
~ ?
?
?
//
創(chuàng)建索引
??
?public void indexFiles() {
?????
?
?//
創(chuàng)建索引文件存放路徑
??????
?File indexDir = new File("E:\\lucene_Learning\\lucene-2.0.0src\\src\\demo\\index");
?
??????
?try {
??????????
?Date start = new Date();
?????????
?
?//
創(chuàng)建分析器
,
主要用于從文本中抽取那些需要建立索引的內(nèi)容
,
把不需要參與建索引的文本內(nèi)容去掉
.
??????????
?//
比如去掉一些
a the
之類(lèi)的常用詞
,
還有決定是否大小寫(xiě)敏感
.
??????????
?StandardAnalyzer standardAnalyzer = new StandardAnalyzer();
??????????
?
//
參數(shù)
true
用于確定是否覆蓋原有索引的
??????????
?IndexWriter indexWriter = new IndexWriter(indexDir, standardAnalyzer, true);
??????????
?indexWriter.setMergeFactor(100);
??????????
?indexWriter.setMaxBufferedDocs(100);
??????????
?
//
只索引這個(gè)
Field
的前
5000
個(gè)字,默認(rèn)為
10000
?????
?
????
?indexWriter.setMaxFieldLength(5000);
?????????
?
?//
從數(shù)據(jù)庫(kù)取出所有紀(jì)錄
??????????
?List articleList = articleManager.getArticles(null);
??????????
?for (int i = 0; i < articleList.size(); i++) {
??????????????
?Article article = (Article) articleList.get(i);
??????????????
?
//
在
Document
方法是創(chuàng)建索引的具體代碼
??????????????
?Document doc = Document(article);
??????????????
?indexWriter.addDocument(doc);
??????????
?}
??????????
?
// Optimize
的過(guò)程就是要減少剩下的
Segment
的數(shù)量
,
盡量讓它們處于一個(gè)文件中
.
??????????
?indexWriter.optimize();
????????
?
?
?indexWriter.close();
??????????
?Date end = new Date();
??????????
?System.out.println("create index: " + (end.getTime() - start.getTime()) + " total milliseconds");
??????
?} catch (IOException e) {
??????????
?System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
??????
?}
??
?}
??
?public static Document Document(Article article)
??????????
?throws java.io.IOException {
??????
?Document doc = new Document();
??????
?
//
為
article
表的主健創(chuàng)建索引,關(guān)于
Field
的幾個(gè)參數(shù)下面有詳細(xì)解釋
??????
?Field fieldId = new Field("uid", article.getArticleId(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.YES);
??????
?
//
為
detail
字段創(chuàng)建索引,
detail
在
DB
中是
clob
字段,內(nèi)容為
html
文本
??????
?String contentHtml = article.getDetail();
??????
?Reader read = new StringReader(contentHtml);
???
??
?
?//
用
HTMLParser
把
detail
字段中的
HTML
分析成文本在索引
??????
?// HTMLParser
這個(gè)類(lèi)可以在
lucene
的
demo
中找到
??????
?HTMLParser htmlParser = new HTMLParser(read);
??????
?BufferedReader breader = new BufferedReader(htmlParser.getReader());
??????
?String htmlContent ="";
??????
?String tempContent = breader.readLine();
??????
?while (tempContent != null && tempContent.length() > 0) {
??????????
?htmlContent = htmlContent + tempContent;
??????????
?tempContent = breader.readLine();
??????
?}
??????
?Field fieldContents = new Field("content", htmlContent,
??????????????
?Field.Store.COMPRESS, Field.Index.TOKENIZED,Field.TermVector.YES);
??????
?// db
中的每條紀(jì)錄對(duì)應(yīng)一個(gè)
doc
,每個(gè)字段對(duì)應(yīng)一個(gè)
field
??????
?doc.add(fieldId);
??????
?doc.add(fieldContents);
??????
?return doc;
??
?}
?
?
?//
搜索文件,
keyword
是你在頁(yè)面上輸入的查找關(guān)鍵字,這里查找的是
detail
字段
??
?public List searchFiles(String keyword){
??????
?String index = "E:\\lucene_Learning\\lucene-2.0.0src\\src\\demo\\index";
??????
?
// hitsList
用來(lái)保存
db
的紀(jì)錄,這些紀(jì)錄可以通過(guò)查詢(xún)結(jié)果取到
??????
?List hitsList = new ArrayList();
??????
?try {
??????????
?Date start = new Date();
??????????
?IndexReader reader = IndexReader.open(index);
??????????
?Searcher searcher = new IndexSearcher(reader);
??????????
?Analyzer analyzer = new StandardAnalyzer();
??????????
?QueryParser parser = new QueryParser("content", analyzer);
??????????
?
//
解析查詢(xún)關(guān)鍵字,比如輸入的是以空格等分開(kāi)的多個(gè)查詢(xún)關(guān)鍵字,這里解析后,可以多條件查詢(xún)
??????????
?Query query = parser.parse(keyword);
??????????
?
// hits
用來(lái)保存查詢(xún)結(jié)果,這里的
hits
相當(dāng)于
sql
中的
result
??????????
?Hits hits = searcher.search(query);
?????
?????
?for (int i = 0; i < hits.length(); i++) {
??????????????
?Document doc = hits.doc(i);
??????????????
?
//
獲得
article
表的主健
??????????????
?String id = doc.get("uid");
?????????????
?
?//
根據(jù)主健去
db
中取紀(jì)錄,返回到
hitsList
中
??????????????
?try {
??????????????????
?Article article = articleManager.getArticle(id);
??????????????
?} catch (ObjectRetrievalFailureException e) {
??????????????????
?article = null;
??????????????
?}
?????????????
??????
?
?
//
如果沒(méi)有找到該紀(jì)錄,表示該紀(jì)錄已經(jīng)不存在,不必添加到
hitsList
中
??????????????
?if(article!=null) ?hitsList.add(article);
??????????
?}
??????????
?searcher.close();
??????????
?reader.close();
??????????
?Date end = new Date();
??????????
?System.out.println("search files: " + (end.getTime() - start.getTime()) + " total milliseconds");
??????
?} catch (IOException e) {
??????????
?System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
??????
?} catch (ParseException e) {
??
?
???????
?System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
??????
?}
??
????
?return hitsList;
??
?}
?
?
?//
刪除索引
??
?public void deleteIndex(){
??????
?String index = "E:\\lucene_Learning\\lucene-2.0.0src\\src\\demo\\index";
??????
?try {
??????????
?Date start = new Date();
??????????
?IndexReader reader = IndexReader.open(index);
??????????
?int numFiles = reader.numDocs();
??????????
?for (int i = 0; i < numFiles; i++) {
??????????????
?
//
這里的刪除只是給文檔做一個(gè)刪除標(biāo)記,你可以看到執(zhí)行
deleteDocument
后會(huì)產(chǎn)生一個(gè)
del
后綴的文件,
??????????????
?//
用來(lái)記錄這些標(biāo)記過(guò)的文件
??????????????
?reader.deleteDocument(i);
??????????
?}
??????????
?reader.close();
??????????
?Date end = new Date();
??????????
?System.out.println("delete index: " + (end.getTime() - start.getTime()) + " total milliseconds");
??????
?} catch (IOException e) {
????????
??
?System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
??????
?}
?
??
?}
?
?
?//
恢復(fù)已刪除的索引
??
?public void unDeleteIndex(){
??????
?String index = "E:\\lucene_Learning\\lucene-2.0.0src\\src\\demo\\index";
??????
?try {
??
????????
?IndexReader reader = IndexReader.open(index);
??????????
?reader.undeleteAll();
??????????
?reader.close();
??????
?} catch (IOException e) {
??????????
?System.out.println(" caught a " + e.getClass() + "\n with message: " + e.getMessage());
????
??
?}
?
}
?
Field
就像我們學(xué)過(guò)的數(shù)據(jù)庫(kù)中的字段,簡(jiǎn)單的說(shuō),就是一個(gè)名值對(duì)。這個(gè)域有三種屬性,分別是
isStored -
是否被存儲(chǔ)
isIndexed -
是否被索引
isTokenized -
是否分詞
這些屬性的組合又構(gòu)成了四種不同類(lèi)型的
Field
,而且各有用途
?
|
Stored
|
Indexed
|
Tokenized
|
Keyword
|
Y
|
Y
|
N
|
UnIndexed
|
Y
|
N
|
N
|
UnStored
|
N
|
Y
|
Y
|
Text: String
|
Y
|
Y
|
Y
|
Text : Reader
|
N
|
Y
|
Y
|
?
關(guān)于
Field
,
2.0.0
版本和
1.4.3
版本方法相比改動(dòng)比較大,具體見(jiàn)下表
?
1.4.3
版本中的下面方法都被
Field(String name, String value, Store store, Index index, TermVector termVector)
取代
Keyword(String name, String value) // only version 1.4.3
存儲(chǔ)、索引、不分詞,用于
URI
(比如
MSN
聊天記錄的日期域、比如
MP3
文件的文件全路徑等等)
Field(String name, String value, Field.Store.YES, Field.Index.UN_TOKENIZED) // version 2.0.0
UnIndexed(String name, String value) // only version 1.4.3
存儲(chǔ)、不索引、不分詞,比如文件的全路徑
Field(String name, String value,Field.Store.YES, Field.Index.NO)// version 2.0.0
UnStored(String name, String value) // only version 1.4.3
不存儲(chǔ)、索引、分詞,比如
HTML
的正文、
Word
的內(nèi)容等等,這部分內(nèi)容是要被索引的,但是由于具體內(nèi)容通常很大,沒(méi)有必要再進(jìn)行存儲(chǔ),可以到時(shí)候根據(jù)
URI
再來(lái)挖取。所以,這部分只分詞、索引,而不存儲(chǔ)。
Field(String name, String value,Field.Store.YES, Field.Index.TOKENIZED)// version 2.0.0
Text(String name, String value) // only version 1.4.3
存儲(chǔ)、索引、分詞,比如文件的各種屬性,比如
MP3
文件的歌手、專(zhuān)輯等等。
Field.Store.YES,
Field(String name, String value,Field.Index.TOKENIZED)// version 2.0.0
Text(String name, Reader value) // only version 1.4.3
Field(String name, Reader reader)
?
// version 2.0.0
不存儲(chǔ)、索引、分詞。
版權(quán)所有:
(xiaodaoxiaodao)
藍(lán)小刀
?
?
xiaodaoxiaodao@gmail.com