基本概念
Token
Token在Lucene與在自然語言處理(NLP汗洒,Natural-language processing)中的概念相同拂募,表示“詞元”穷躁。詞元即自然語言中的基本單位:在中文表現(xiàn)為一個獨立的字或詞,在英文中表現(xiàn)為一個單詞典奉。
將句子處理成Token的過程酝掩,稱為分詞鳞芙,而完成分詞工作的組件稱為分詞器(Analyzer)。分詞器的選擇根據(jù)語言、場景而不同:用戶可以選擇Lucene中內(nèi)置的分詞器原朝,也可以自定義實現(xiàn)分詞器闯割。
總的來說,中文分詞要比英文分詞復(fù)雜竿拆。本篇介紹英文分詞宙拉,有關(guān)中文分詞的內(nèi)容,后續(xù)單獨介紹丙笋。
在Lucene中谢澈,分詞通常包含以下步驟:
- 拆分單詞(Split):像英文這種帶有自然分隔(空格、標(biāo)點符號)的語言御板,可以簡單地按照分隔符進(jìn)行拆分锥忿。
- 排除停用詞(Stop Words):自然語言中含有大量沒有實際含義的功能詞,在自然語言處理中怠肋,遇到這類詞敬鬓,就會停止處理,所以稱這些功能詞為停用詞笙各。停用詞通常表現(xiàn)為冠詞(eg. a钉答、the)、介詞(eg. on杈抢、in)数尿、副詞(eg. how、when)或連詞(eg. and)惶楼。在分詞時排除停用詞右蹦,既減少了索引量,又提高了檢索效率和效果歼捐。關(guān)于停用詞的段子:從品牌辨識度何陆、圖形獨特性和美感角度,如何評價中國移動新品牌「and 和」的名稱及其 logo 設(shè)計豹储? - 傅渥成的回答 - 知乎
- 詞干提却ぁ( Stemming):英文中含有名詞復(fù)數(shù)、第三人稱單數(shù)颂翼、過去時晃洒、進(jìn)行時等一系列衍生詞慨灭,一般而言朦乏,我們真正關(guān)心的是它們的詞根。抽取單詞詞根的過程稱為詞干提取氧骤。主流的Stemming算法有Porter stemming algorithm呻疹、Lovins stemming algorithm、Lancaster(Paice/Husk) stemming algorithm筹陵。Lucene 使用了 Snowball 語言編寫的詞干提取算法刽锤,并將其封裝在了lucene-analyzers-common包中镊尺。
- 單詞小寫化(Lower Case):針對搜索詞大小寫不敏感的情況,在分詞時并思,會把單詞統(tǒng)一轉(zhuǎn)化為小寫形式庐氮。
Field
Field(域)可以類比關(guān)系型數(shù)據(jù)庫中的字段的概念。Field包含三個部分:名稱宋彼、類型弄砍、值。
常用的Field有數(shù)值型输涕、字符串型音婶、文本型。
下面是常用的Field與關(guān)系型數(shù)據(jù)庫字段的對照關(guān)系:
字段類型 | 關(guān)系型數(shù)據(jù)庫(以MySQL為例) | Lucene | 說明 |
---|---|---|---|
數(shù)值型 | int莱坎、bigint衣式、double | IntPoint、LongPoint檐什、DoublePoint | - |
字符串型 | varchar | StringField | StringField中的值不會分詞 |
文本型 | text | TextField | TextField中的值會做分詞處理 |
日期型 | date碴卧、timestamp、datetime | - | Lucene沒有提供日期型Field乃正,但是可以根據(jù)需要將日期轉(zhuǎn)為數(shù)值型或字符串型Field |
Document
Document(文檔)是Field的集合螟深。Document可以類比為關(guān)系型數(shù)據(jù)庫中的記錄,不同的是烫葬,Document并非結(jié)構(gòu)化的界弧,并沒有schema的約束:
- 不同Document對象中包含的Field并不要求一致(半結(jié)構(gòu)化)
- 同一Document對象可以包含多個同名的Field
舉個例子:
? 一個Document可以描述一個人的信息,可能包含姓名搭综、年齡等字段垢箕;
? 另外一個Document可以描述一本書的信息,可能包含書名兑巾、作者等字段条获,并且可以有多個名為作者的字段可霎。
Directory
Directory是Document的集合洋魂,描述了Lucene索引的存放位置,可類比關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)庫:
- JDBC操作關(guān)系型數(shù)據(jù)庫時绷蹲,我們首先獲取Connection對象堂油;操作Lucene時修档,首先要獲取Directory對象
- JDBC提供了Statement對象對數(shù)據(jù)庫進(jìn)行讀寫;而Lucene的讀寫操作分別由不同的類實現(xiàn):IndexWriter負(fù)責(zé)寫操作府框,IndexReader負(fù)責(zé)讀操作吱窝。
數(shù)據(jù)庫有MySQL、Oracle之分,Directory也有不同的實現(xiàn):
Directory子類 | 描述 |
---|---|
SimpleFSDirectory | 最簡單的Directory子類院峡,使用java.io.* API將文件存入文件系統(tǒng)兴使。不能很好支持多線程操作 |
NIOFSDirectory | 使用java.nio.* API將文件保存至文件系統(tǒng)。能很好支持除Windows之外的多線程操作照激,原因是Sun的JRE在Windows平臺上長期存在問題 |
MMapDirectory | 使用內(nèi)存映射I/O進(jìn)行文件訪問发魄。對于64位JRE來說是一個很好的選擇,對于32位JRE并且索引尺寸相對較小時也可以使用該類 |
RAMDirectory | 將所有文件都存入RAM |
FIleSwitchDirectory | 使用兩個文件目錄俩垃,根據(jù)文件擴展名在兩個目錄之間切換使用 |
表格中內(nèi)容摘自《Lucene In Action》一書
如果選擇將索引保存在文件系統(tǒng)中欠母,可以顯式指定使用哪個Directory子類,也可以使用Lucene提供的工廠方法吆寨,讓Lucene為你做最優(yōu)選擇:
org.apache.lucene.store.FSDirectory#open(java.nio.file.Path)
Query
Query類似關(guān)系型數(shù)據(jù)庫中的SQL語句赏淌。與關(guān)系型數(shù)據(jù)庫類似,Lucene提供了以下的基本查詢:
查詢類型 | 關(guān)系型數(shù)據(jù)庫 | Lucene |
---|---|---|
精確查詢 | xxx = ? | TermQuery |
范圍查詢 | xxx BETWEEN? AND ? | PointRangeQuery |
模糊查詢 | xxx LIKE '%?%' | PrefixQuery啄清、RegexpQuery |
組合查詢 | (...) AND (...) OR (...) | BooleanQuery |
倒排索引
倒排索引(Inverted Index六水,也叫反向索引)是相較正排索引(Forward Index,也叫正向索引)而言的辣卒。
簡單來說掷贾,正排索引描述的是每個文檔包含哪些詞;倒排索引描述的是某個詞出現(xiàn)在哪些文檔中荣茫。
假設(shè)有如下編號的文檔:
1. the fox jumps over the dog
2. god save dog
建正排索引如下:
文檔編號 | 包含單詞 |
---|---|
1 | {the, fox, jumps, over, dog} |
2 | {god, save, dog} |
建倒排索引如下:
單詞 | 包含該單詞的文檔 |
---|---|
the | {1} |
fox | {1} |
... | ... |
dog | {1, 2} |
不難發(fā)現(xiàn)想帅,如果要搜索哪些文檔包含給定的單詞,正排索引需要O(N)的時間啡莉,而倒排索引需要O(1)的時間港准。
Lucene中的倒排索引要比這復(fù)雜得多,不僅存儲包含某單詞的文檔編號咧欣,而且會存儲該單詞在各文檔中的出現(xiàn)頻率以及位置信息等浅缸。
以上是Lucene的基本概念,下一篇開始魄咕,會介紹Lucene中的CRUD操作衩椒。