Apache Lucene 3.x推薦教程

介紹:

Apache Lucene 是一個基於 Java 的全文檢索工具包,你可以利用它來爲你的應用程序加入索引和檢索功能。Lucene 目前是著名的 Apache Jakarta 家族中的一個開源項目,也是目前最爲流行的基於 Java 開源全文檢索工具包。

   

第一部分:概述

  1. 我們在很多地方都可以看到搜索功能

  • Windows系統中的有搜索功能:打開"我的電腦",按"F3"就可以使用查找的功能,查找指定的文件或文件夾。搜索的範圍是整個電腦中的文件資源。
  • Eclipse中的幫助子系統:點擊HelpàHelp Contents,可以查找出相關的幫助信息。搜索的範圍是Eclipse的所有幫助文件。
  • BBSBLOG等系統中提供的搜索文章的功能,如這裏的貼吧的例子。搜索的範圍是系統內的文章數據(都在數據庫中)。
  • 搜索引擎,如BaiduGoogle等,可以查詢到互聯網中的網頁、PDFDOCPPT、圖片、視頻等。下圖是使用百度搜索的效果:

 

以上的查詢功能都類似。都是查詢的文本內容,都是相同的查詢方式,即找出含有指定字符串的資源,不同的只是查詢範圍(分別爲硬盤、所有幫助文件、數據庫、互聯網)。

 

  1. 什麼是全文檢索

對於搜索,按被搜索的資源類型,分爲兩種:可以轉爲文本的、多媒體類型。我們上一節提到的搜索功能都是搜索的可以轉爲文本的資源(第一種)。注意,百度或谷歌提供的音樂或視頻搜索不是多媒體搜索,他們是按文件名搜索。在智能手機上有一款音樂搜索的軟件,可以讓他聽10秒鐘的音樂,然後他就能上網找出這段音樂的名稱、演奏者等信息。這是多媒體搜索。

按搜索的方式,上一節提到的搜索功能都是不處理語義,只是找出包含指定詞的所有資源(只對詞進行匹配)。下圖就是顯示"中國的首都是哪裏"這個搜索要求對應的結果,可以看到,是沒有"北京"這個結果的,結果頁面都是出現了這些詞的網頁:

 

全文檢索(Full-Text Retrieval是指以文本作爲檢索對象,找出含有指定詞彙的文本。全面、準確和快速是衡量全文檢索系統的關鍵指標。

關於全文檢索,我們要知道:1,只處理文本。2,不處理語義。3,搜索時英文不區分大小寫。4,結果列表有相關度排序。

在信息檢索工具中,全文檢索是最具通用性和實用性的。

  1. 學完後能做什麼

我們使用Lucene,主要是做站內搜索,即對一個系統內的資源進行搜索。如BBSBLOG中的文章搜索,網上商店中的商品搜索等。使用Lucene的項目有EclipseJira等。一般不做互聯網中資源的搜索,因爲不易獲取與管理海量資源(專業搜索方向的公司除外)。

所以,學完Lucene後我們就可以爲自已的系統增加全文檢索的功能。跟這個學習內容相關的練習爲:爲"傳智手播客貼吧"增加搜索其中的文章的功能。

  1. 全文檢索不同於數據庫搜索

全文檢索不同於數據庫的SQL查詢。(他們所解決的問題不一樣,解決的方案也不一樣,所以不應進行對比)。在數據庫中的搜索就是使用SQL,如:SELECT * FROM t WHERE content like '%ant%'。這樣會有如下問題:

  • 匹配效果:如搜索ant會搜索出planting。這樣就會搜出很多無關的信息。
  • 相關度排序:查出的結果沒有相關度排序,不知道我想要的結果在哪一頁。我們在使用百度搜索時,一般不需要翻頁,爲什麼?因爲百度做了相關度排序:爲每一條結果打一個分數,這條結果越符合搜索條件,得分就越高,叫做相關度得分,結果列表會按照這個分數由高到低排列,所以第1頁的結果就是我們最想要的結果。
  • 全文檢索的速度大大快於SQLlike搜索的速度。這是因爲查詢方式不同造成的,以查字典舉例:數據庫的like就是一頁一頁的翻,一行一行的找,而全文檢索是先查目錄,得到結果所在的頁碼,再直接翻到這一頁。

 

所以數據庫搜索不能替代全文檢索。

  • 第二部分:入門
  1. 基礎概念1HelloWorld前)

全文檢索就如同ORM,是一個概念。ORM的框架有很多種:HibernateTopLinkiBatis等,我們之前學習的是Hibernate。同樣的,全文檢索領域中也有多種框架,Lucene就是其中的一個用開源的全文檢索框架。

Lucene的主頁爲:http://lucene.apache.org/。本文檔中所使用的Lucene3.0.1的版本。以下兩小節是Lucene中重要的概念。

  1. 全文檢索的工作流程

如果信息檢索系統在用戶發出了檢索請求後再去互聯網上找答案,根本無法在有限的時間內返回結果。所以要先把要檢索的資源集合放到本地,並使用某種特定的結構存儲,稱爲索引,這個索引的集合稱爲索引庫。由於索引庫的結構是按照專門爲快速查詢設計的,所以查詢的速度非常快。我們每次搜索都是在本地的索引庫中進行,如下圖:

從圖片上可以看出,我們不僅要搜索,還要保證數據集合與索引庫的一致性。所以對於全文檢索功能的開發,要做的有兩個方面:索引庫管理(維護索引庫中的數據)、在索引庫中進行搜索。而Lucene就是操作索引庫的工具。

 

  1. 使用LuceneAPI操作索引庫

索引庫是一個目錄,裏面是一些二進制文件,就如同數據庫,所有的數據也是以文件的形式存在文件系統中的。我們不能直接操作這些二進制文件,而是使用Lucene提供的API完成相應的操作,就像操作數據庫應使用SQL語句一樣。

對索引庫的操作可以分爲兩種:管理與查詢。管理索引庫使用IndexWriter,從索引庫中查詢使用IndexSearcherLucene的數據結構爲DocumentFieldDocument代表一條數據,Field代表數據中的一個屬性。一個Document中有多個FieldField的值爲String型,因爲Lucene只處理文本。

我們只需要把在我們的程序中的對象轉成Document,就可以交給Lucene管理了,搜索的結果中的數據列表也是Document的集合。

有了這些概念,可以寫HelloWorld了,其他的概念可以在寫完HelloWorld後再進行說明。

 

  1. 基礎概念2HelloWorld後)

    1. 索引庫結構——倒排序索引

我們需要對文檔進行預處理,建立一種便於檢索的數據結構,以此來提高信息檢索的速度,這種數據結構就是索引。目前廣泛使用的一種索引方式是倒排序索引。

倒排序索引的原理就如同查字典。要先查目錄,得到數據對應的頁碼,在直接翻到指定的頁碼。不是在文章中找詞,而是從目錄中找詞所在的文章。這需要在索引庫中生成一個詞彙表(目錄),在詞彙表中的每一個條記錄都是類似於"à所在文檔的編號列表"的結構,記錄了每一個出現過的單詞,和單詞出現的地方(哪些文檔)。查詢時先查詞彙表,得到文檔的編號,再直接取出相應的文檔。

把數據轉成指定格式放到索引庫中的操作叫做建立索引。建立索引時,在把數據存到索引庫後,再更新詞彙表。進行搜索時,先從檢索詞彙表開始,然後找到相對應的文檔。如果查詢中僅包含一個關鍵詞,則在詞彙表中找到該單詞,並取出他對應的文檔就可以了。如果查詢中包含多個關鍵詞,則需要將各個單詞檢索出的記錄進行合併再取出相應的文檔記錄。

如果詞彙表中有一個詞"傳智播客"對應的文檔編號列表爲"1"。現在又有添加了一個包含"傳智播客"的文檔,則詞彙表中的"傳智播客"詞後對應的編號列表變成了"1,2"。因爲關鍵詞的數量受實際語言的限制,所以不用擔心詞彙表會變的很大。

  1. 索引文件的檢索與維護,更新是先刪除後創建

維護倒排索引有三個操作:添加、刪除和更新文檔。但是更新操作需要較高的代價。因爲文檔修改後(即使是很小的修改),就可能會造成文檔中的很多的關鍵詞的位置都發生了變化,這就需要頻繁的讀取和修改記錄,這種代價是相當高的。因此,一般不進行真正的更新操作,而是使用"先刪除,再創建"的方式代替更新操作。

  1. 建立索引的執行過程(StoreIndex

在建立索引時,先要把文檔存到索引庫中,還要更新詞彙表。如下圖:

  1. 我們做的操作:把數據對象轉成相應的Document,其中的屬性轉爲Field
  2. 我們做的操作:調用工具IndexWriteraddDocument(doc),把Document添加到索引庫中。
  3. Lucene做的操作:把文檔存到索引庫中,並自動指定一個內部編號,用來唯一標識這條數據。內部編號類似於這條數據的地址,在索引庫內部的數據進行調整後,這個編號就可能會改變,同時詞彙表中引用的編號也會做相應改變,以保證正確。但我們如果在外面引用了這個編號,前後兩次去取,得到的可能不是同一個文檔!所以內部編號最好只在內部用。
  4. Lucene做的操作:更新詞彙表。把文本中的詞找出並放到詞彙表中,建立與文檔的對應關係。要把哪些詞放到詞彙表中呢,也就是文本中包含哪些詞呢?這就用到了一個叫做Analyzer(分詞器)的工具。他的作用是把一段文本中的詞按規則取出所包含的所有詞。對應的是Analyzer類,這是一個抽象類,切分詞的具體規則是由子類實現的,所以對於不同的語言(規則),要用不同的分詞器。如下圖:

    在把對象的屬性轉爲Field時,相關代碼爲:doc.add(new Field("title", article.getTitle(), Store.YES, Index.ANALYZED))。第三與第四個參數的意思爲:

枚舉類型

枚舉常量

說明

Store

NO

不存儲屬性的值

YES

存儲屬性的值

Index

NO

不建立索引

ANALYZED

分詞後建立索引

NOT_ANALYZED

不分詞,把整個內容作爲一個詞建立索引

說明:Store是影響搜索出的結果中是否有指定屬性的原始內容。Index是影響是否可以從這個屬性中查詢(No),或是查詢時可以查其中的某些詞(ANALYZED),還是要把整個內容作爲一個詞進行查詢(NOT_ANALYZED)。

  1. 從索引庫中搜索的執行過程(QueryParserTopDocsScoreDoc

在進行搜索時,先在詞彙表中查找,得到符合條件的文檔編號列表。再根據文檔編號真正的去取出數據(Document)。如下圖:

 

  1. 把要查詢字符串轉爲Query對象。這就像在Hibernate中使用HQL查詢時,也要先調用Session.createQuery(hql)轉成HibernateQuery對象一樣。把查詢字符串轉換成Query是使用QueryParser,或使用MultiFieldQueryParser。查詢字符串也要先經過Analyzer(分詞器)。要求搜索時使用的Analyzer要與建立索引時使用的Analzyer要一致,否則可能搜不出正確的結果。
  2. 調用IndexSearcher.search(),進行查詢,得到結果。此方法返回值爲TopDocs,是包含結果的多個信息的一個對象。其中有totalHits 代表決記錄數,ScoreDoc的數組。ScoreDoc是代表一個結果的相關度得分與文檔編號等信息的對象。
  3. 取出要用到的數據列表。調用IndexSearcher.doc(scoreDoc.doc)以取出指定編號對應的Document數據。在分頁時要用到:一次只取一頁的數據。

 

  1. HelloWorld

  • 準備場景
  • 添加Lucene環境
  • 完成功能
    • 建立索引
    • 從索引庫中搜索

 

要加入的jar包有:

  • lucene-core-3.0.1.jar(核心包)
  • contrib\analyzers\common\lucene-analyzers-3.0.1.jar(分詞器)
  • contrib\highlighter\lucene-highlighter-3.0.1.jar(高亮)
  • contrib\memory\lucene-memory-3.0.1.jar(高亮)
    • 第三部分:深入
  1. 索引庫管理

    1. IndexWriter

構造方法1IndexWriter(Directory d, Analyzer a, MaxFieldLength mfl)

 

構造方法2IndexWriter(Directory d, Analyzer a, boolean create, MaxFieldLength mfl),第三個參數指定,true表示建立新的索引庫或覆蓋現有的索引庫(刪除後重建);false表示使用已有的索引庫,如果不存在,就報錯。

 

commit()

rollback()

close()

  1. 使用IndexDao封裝對索引庫的增刪改查1

提出問題:所有的數據(對象),我們都要存到數據庫中。對於要進行搜索的數據,還要存到索引庫中,以供搜索。一份數據同時存到數據庫與索引庫中(格式不同),就要想辦法保證他們的狀態一致。否則,就會影響搜索結果。

解決思路:對於上一段提出的問題:保證索引庫中與數據庫中的數據一致(只要針對要進行搜索的數據)。我們採用的方法是,在數據庫中做了相應的操作後,在索引庫中也做相應的操作。具體的索引庫操作,是通過調用相應的IndexDao方法完成的。IndexDao類似於數據庫層的Dao

我們目前只關注IndexDao中的每個方法的作用(怎麼用起來方便就怎麼設計)。現在不需要關心IndexDao的每個方法怎麼實現,因爲那是下一步的事情。設計IndexDao如下:

 

IndexDao的使用:

PublishAction.execute(){ // 發表文章

    actionForm à article對象

    articleDao.save( article ); // 保存到數據庫

    articleIndexDao.save( article ); // 保存到索引庫

}

DeleteAction.execute(){ // 刪除文章

    articleDao.delete( id ); // 從數據庫中刪除

    articleIndex.delete( id ); // 從索引庫中刪除

}

UpdateAction.execute(){ // 更新文章

    actionForm à article對象

    articleDao.update( article ); // 更新數據庫中的相應數據

    articleIndexDao.update( article ); // 更新索引庫中的相應數據

}

 

 

  1. 使用工具類做對象與Document之間的相互轉換

我們在應用程序中使用對象表示數據。在數據庫中使用的是表記錄,所以存在來回轉換的問題。同樣,要索引庫中使用的是Document,也存在來回轉換的問題。如下圖:

 

對於一個要進行搜索的實體對象,我們會寫一個對應的工具類,其中有兩個方法:

Document Object2Document(Object object); // 對象àDocument

Object Document2Object(Document doc); // Documentà對象

在轉換時,對象中的屬性對應Document中的Field。由於Lucene只處理文本,所有所有的屬性值在存儲前都要先轉成字符串。使用構造方法:Field(String name, String value, Store store, Index index)

 

StoreIndex都是枚舉類型。Store:指定是否把當前屬性值的原始內容存儲到索引庫中。如果存儲(YES),在搜索出相應數據時這個屬性就有原始的值;如果不存儲(NO),得到的數據的這個屬性的值爲nullIndex:指定是否建立索引(詞彙表)。建立索引才能被搜索到。不可以不存儲也不建立索引(沒有意義)。

// Store 指定當前字段的數據要不要存到索引庫中

// Index 指定當前字段的數據是否可以被搜索(是否更新詞彙表)

 

索引設置的一些建議:

1) 儘量減少不必要的存儲

2) 不需要檢索的內容不要建立索引

3) 非文本格式需要提前轉化

4)需要整體存放的內容不要分詞

 

NumericUtilsDateTools

如果屬性的類型不是字符串,則要先進轉換:如果是數字類型,使用NumericUtils。如果是日期類型,則使用DataTools

  1. 實現IndexDao中的方法:建立、刪除、更新索引

索引庫的管理操作操作是通過類IndexWriter完成的。創建實例是使用構造方法:IndexWriter(Directory d, Analyzer a, MaxFieldLength mfl)。用完後要調用IndexWriter.close()方法釋放資源。

 

  1. 建立索引:保存文檔到索引庫中。
    1. 把數據轉成Document對象的形式。
    2. 調用方法IndexWriter.addDocument(Document doc)

 

  1. 刪除索引:刪除所有包含指定Term的文檔。
    1. 生成用於確定要刪除的文檔的Term
    2. 調用方法IndexWriter.deleteDocuments(Term term)

說明:在生成Term時,一般。如果有多個文檔含有指定的Term,則都會被刪掉。

 

  1. 更新索引:實際執行的是先刪除,後創建的操作。(參見前面的索引文件的檢索與維護)
    1. 把要更新後的對象轉爲Document對象
    2. 生成用於確定要更新的文檔的Term
    3. 調用方法IndexWriter.updateDocument(Term term, Document doc)

說明:如果有多個文檔含有指定的Term,更新後就只有一條記錄(刪掉所有,再創建一個)。如果沒有文檔含有指定的記錄,不會報錯,更新後有一條(新創建的)記錄。

 

 

  1. 索引庫文件優化

    1. 合併索引庫文件

IndexWriter.optimize()

indexWriter.setMergeFactor(int)

 

 

  1. 使用RAMDirectory

LuceneAPI接口設計的比較通用,輸入輸出結構都很像數據庫的表==>記錄==>字段,所以很多傳統的應用的文件、數據庫等都可以比較方便的映射到Lucene的存儲結構/接口中。總體上看:可以先把Lucene當成一個支持全文索引的數據庫系統。

Lucene的索引存儲位置使用的是一個接口(抽象類),也就可以實現各種各樣的實際存儲方式(實現類、子類),比如存到文件系統中,存在內存中、存在數據庫中等等。Lucene提供了兩個子類:FSDirectoryRAMDirectory

  1. FSDirectory:在文件系統中,是真實的文件夾與文件。
  2. RAMDirectory:在內存中,是模擬的文件夾與文件。與FSDirectory相比:1因爲沒有IO操作,所以速度快。2,因爲在內存中,所以在程序退出後索引庫數據就不存在了。

 

索引庫的相關操作:

  1. 合併索引庫:Directory.addIndexes()
  2. 索引的優化:IndexWriter.optimize()

看看Compass中的Directory的子類,怎麼存到數據庫中的。

  1. 在索引庫中搜索(查詢語法與Query對象)

    1. IndexSearcher

在索引庫中進行搜索是使用類IndexSearcher。創建其實例的構造方法爲:IndexSearcher (Directory path)。用完後要調用IndexSearcher.close()方法釋放資源。

  1. 通過QueryParser解析用戶的查詢字符串進行搜索

  1. QueryParserMultiFieldQueryParser

查詢分析器,處理用戶輸入的查詢條件。把用戶輸入的非格式化檢索詞轉化成後臺檢索可以理解的Query對象。使用的構造方法爲:QueryParser(Version matchVersion, String f, Analyzer a)

 

  1. MultiFieldQueryParser

QueryParser的子類。與父類相比,MultiFieldQueryParser可以在多個屬性中搜索。使用的構造方法爲:MultiFieldQueryParser(Version matchVersion, String[] fields, Analyzer analyzer)

  1. 通過構建各種Query對象進行查詢(Query的子類)

Query:抽象類,必須通過一系列子類來表述檢索的具體需求。

 

TermQuery

關鍵詞查詢

NumericRangeQuery

範圍查詢。使用靜態方法構造實例:

newIntRange(final String field,

Integer min, Integer max,

final boolean minInclusive, final boolean maxInclusive)

newLongRange(final String field,

Long min, Long max,

final boolean minInclusive, final boolean maxInclusive)

newFloatRange(final String field,

Float min, Float max,

final boolean minInclusive, final boolean maxInclusive)

newDoubleRange(final String field,

Double min, Double max,

final boolean minInclusive, final boolean maxInclusive)

WildcardQuery

通配符查詢

PhraseQuery

短語查詢

public void add(Term term, int position)

public void setSlop(int s)

 

例:add( new Term("name", "lucene", 1);

add(new Term("name", "教程", 3);

代表搜索的是"Lucene 教程",?表示中間隔一個詞。

setSlop(2);

代表這兩個詞中間可以最多隔2個詞

BooleanQuery

public void add(Query query, Occur occur)

 

Occur 用於表示布爾查詢子句關係的類,包括:

Occur.MUSTOccur.MUST_NOTOccur.SHOULD

 

  1. MUSTMUST:取得連個查詢子句的交集。
  2. MUSTMUST_NOT:包含MUST並且查詢結果中不包含MUST_NOT的檢索結果。
  3. SHOULDSHOULD,表示""關係,最終檢索結果爲所有檢索子句的並集。

 

使用時注意:

  1. 單獨使用MUST_NOT:無意義,檢索無結果。(也不報錯)
  2. MUST_NOTMUST_NOT:無意義,檢索無結果。(也不報錯)

 

  1. 單獨使用SHOULD:結果相當於MUST
  2. SHOULDMUST_NOT此時SHOULD相當於MUST,結果同MUSTMUST_NOT
  3. MUSTSHOULD:此時SHOULD無意義,結果爲MUST子句的檢索結果。

 

 

// 關鍵詞查詢

@Test

public void testTermQuery() { }

// 範圍查詢

@Test

public void testRangeQuery() { }

// 通配符查詢

@Test

public void testWildcardQuery() { }

// 短語查詢

@Test

public void testPhraseQuery() { }

// 布爾查詢

@Test

public void testBooleanQuery() { }

 

 

  1. 支持分頁

 

  1. 排序(相關度排序與自定義排序)

通過改變文檔Boost值來改變排序結果。Boost是指索引建立過程中,給整篇文檔或者文檔的某一特定屬性設定的權值因子,在檢索時,優先返回分數高的。通過Document對象的setBoost()方法和Field對象的setBoost()方法,可以分別爲DocumentField指定Boost參數。不同在於前者對文檔中每一個域都修改了參數,而後者只針對指定域進行修改。默認情值爲1F,一般不做修改。

 

使用Sort對象定製排序。Sort支持的排序功能以文檔當中的域爲單位,通過這種方法,可以實現一個或者多個不同域的多形式的值排序。時間類型的屬性採用STRING常量。

 

 

  1. 按相關度排序

1,相關度得分是在查詢時根據查詢條件實進計算出來的

2,如果索引庫據不變,查詢條件不變,查出的文檔得分也不變

  1. 按指定的字段排序

If you want to be able to sort results by a Field value, you must add it as a Field that is indexed but not analyzed, using Field.Index.NOT_ANALYZED.

  1. 過濾(Filter

使用Filter可以對搜索結果進行過濾以獲得更小範圍的結果。使用Filter對性能的影響很大(有可能會使查詢慢上百倍)。

使用NumericRangeFilter。也可使用相應的查詢實現一樣的效果。

  1. 高亮(Highlight

需要的jar包爲:

contrib\highlighter\lucene-highlighter-3.0.1.jar

contrib\memory\lucene-memory-3.0.1.jar

 

// 生成高亮器

Formatter formatter = new SimpleHTMLFormatter("<span class='kw'>", "</span>");

Scorer scorer = new QueryScorer(query);

Highlighter highlighter = new Highlighter(formatter, scorer);

highlighter.setTextFragmenter(new SimpleFragmenter(20));

 

// 使用高亮器:對content屬性值進行摘要並高亮

String text = highlighter.getBestFragment(LuceneUtils.getAnalyzer(), "content", doc.get("content"));

// 如果進行高亮的屬性值中沒有要搜索的關鍵字,則返回null

if (text != null) {

    doc.getField("content").setValue(text);

}

  1. Analyzer(分詞器:結構與常用的中文分詞器)

    1. 分詞器結構

創建索引與進行搜索要使用同一個分詞器。

 

 

分詞器的一般工作流程:

  1. 切分關鍵詞
  2. 去除停用詞

3,對於英文單詞,一般要還做:英文單詞的所有字母轉爲小寫

 

說明:形態還原,是去除單詞詞尾的形態變化,將其還原爲詞的原形。這樣做可以搜索出更多有意義的結果。如搜索sutdent時,也可以搜索出students,這是很有用的。

  1. 停用詞

有些詞在文本中出現的頻率非常高,但是對文本所攜帶的信息基本不產生影響,例如英文的"aantheof",或中文的"的、了、着",以及各種標點符號等,這樣的詞稱爲停用詞(stop word)。文本經過分詞之後,停用詞通常被過濾掉,不會被進行索引。在檢索的時候,用戶的查詢中如果含有停用詞,檢索系統也會將其過濾掉(因爲用戶輸入的查詢字符串也要進行分詞處理)。排除停用詞可以加快建立索引的速度,減小索引庫文件的大小。

 

  1. 對英文的的處理

  2. 中文分詞器

中文的分詞比較複雜,因爲不是一個字就是一個詞,而且一個詞在另外一個地方就可能不是一個詞,如在"帽子和服裝"中,"和服"就不是一個詞。對於中文分詞,通常有三種方式:單字分詞、二分法分詞、詞典分詞。

  • 單字分詞:就是按照中文一個字一個字地進行分詞。如:"我們是中國人"
    效果:""""""""""""。(StandardAnalyzer就是這樣)。
  • 二分法分詞:按兩個字進行切分。如:"我們是中國人",效果:"我們""們是""是中""中國""國人"。(CJKAnalyzer就是這樣)。
  • 詞庫分詞:按某種算法構造詞,然後去匹配已建好的詞庫集合,如果匹配到就切分出來成爲詞語。通常詞庫分詞被認爲是最理想的中文分詞算法。如:"我們是中國人",效果爲:"我們""中國人"。(使用極易分詞的MMAnalyzer。可以使用"極易分詞",或者是"庖丁分詞"分詞器、IKAnalyzer)。

 

 

其他的中文分詞器有:

  1. 極易分詞:MMAnalyzer,最後版本是1.5.3,更新時間是2007-12-05,不支持Lucene3.0
  2. 庖丁分詞:PaodingAnalzyer,最後版本是2.0.4,更新時間是2008-06-03,不支持Lucene3.0

 

 

中文分詞器使用IKAnalyzer,主頁:http://www.oschina.net/p/ikanalyzer

實現了以詞典爲基礎的正反向全切分,以及正反向最大匹配切分兩種方法。IKAnalyzer是第三方實現的分詞器,繼承自LuceneAnalyzer類,針對中文文本進行處理。具體的使用方式參見其文檔。

注意:擴展的詞庫與停止詞文件要是UTF-8的編碼,並且在要文件頭部加一空行。

  1. 測試分詞器

    /**

     *使用批定的分詞器對指定的文本進行分詞,並打印結果

     * @param analyzer

     * @param text

     * @throws Exception

     */

private void testAnalyzer(Analyzer analyzer, String text) throws Exception {

    System.out.println("當前使用的分詞器:" + analyzer.getClass());

 

    TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));

    tokenStream.addAttribute(TermAttribute.class);

 

    while (tokenStream.incrementToken()) {

        TermAttribute termAttribute = tokenStream.getAttribute(TermAttribute.class);

        System.out.println(termAttribute.term());

    }

}

  1. 練習

  1. 文件搜索。數據在文件夾中(文件)。
  2. 文章搜索。數據在數據庫中(記錄)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章