lucene 基本原理整理


基本原理:http://www.cnblogs.com/forfuture1978/archive/2009/12/14/1623594.html

所有過程:http://www.cnblogs.com/forfuture1978/archive/2010/06/13/1757479.html

 

1.什么是索引,為什么需要索引

對非結構化數據也即對全文數據的搜索主要有兩種方法:

一種是順序掃描法(Serial Scanning):所謂順序掃描,比如要找內容包含某一個字符串的文件,就是一個文檔一個文檔的看,對於每一個文檔,從頭看到尾,如果此文檔包含此字符串,則此文檔為我們要找 的文件,接着看下一個文件,直到掃描完所有的文件。如利用windows的搜索也可以搜索文件內容,只是相當的慢。如果你有一個80G硬盤,如果想在上面 找到一個內容包含某字符串的文件,不花他幾個小時,怕是做不到。Linux下的grep命令也是這一種方式。大家可能覺得這種方法比較原始,但對於小數據 量的文件,這種方法還是最直接,最方便的。但是對於大量的文件,這種方法就很慢了。

有人可能會說,對非結構化數據順序掃描很慢,對結構化數據的搜索卻相對較快(由於結構化數據有一定的結構可以采取一定的搜索算法加快速度),那么把我們的非結構化數據想辦法弄得有一定結構不就行了嗎?

這種想法很天然,卻構成了全文檢索的基本思路,也即將非結構化數據中的一部分信息提取出來,重新組織,使其變得有一定結構,然后對此有一定結構的數據進行搜索,從而達到搜索相對較快的目的。

這部分從非結構化數據中提取出的然后重新組織的信息,我們稱之索引

這種說法比較抽象,舉幾個例子就很容易明白,比如字典,字典的拼音表和部首檢字表就相當於字典的索引,對每一個字的解釋是非結構化的,如果字典沒有音節表和 部首檢字表,在茫茫辭海中找一個字只能順序掃描。然而字的某些信息可以提取出來進行結構化處理,比如讀音,就比較結構化,分聲母和韻母,分別只有幾種可以 一一列舉,於是將讀音拿出來按一定的順序排列,每一項讀音都指向此字的詳細解釋的頁數。我們搜索時按結構化的拼音搜到讀音,然后按其指向的頁數,便可找到 我們的非結構化數據——也即對字的解釋

 

2.索引包含哪些東西

首先我們來看為什么順序掃描的速度慢:

其實是由於我們想要搜索的信息和非結構化數據中所存儲的信息不一致造成的。

非 結構化數據中所存儲的信息是每個文件包含哪些字符串,也即已知文件,欲求字符串相對容易,也即是從文件到字符串的映射。而我們想搜索的信息是哪些文件包含 此字符串,也即已知字符串,欲求文件,也即從字符串到文件的映射。兩者恰恰相反。於是如果索引總能夠保存從字符串到文件的映射,則會大大提高搜索速度。

由於從字符串到文件的映射是文件到字符串映射的反向過程,於是保存這種信息的索引稱為反向索引

左邊保存的是一系列字符串,稱為詞典。每個字符串都指向包含此字符串的文檔(Document)鏈表,此文檔鏈表稱為倒排表(Posting List)。

 

3.索引的創建過程
第一步:一些要索引的原文檔(Document)。
    為了方便說明索引創建過程,這里特意用兩個文件為例:
    文件一:Students should be allowed to go out with their friends, but not allowed to drink beer.
    文件二:My friend Jerry went to school to see his students but found them drunk which is not allowed.

第二步:將原文檔傳給分詞組件(Tokenizer)。
    分詞組件(Tokenizer)會做以下幾件事情(此過程稱為Tokenize):
    1. 將文檔分成一個一個單獨的單詞。
    2. 去除標點符號。
    3. 去除停詞(Stop word)。
    所謂停詞(Stop word)就是一種語言中最普通的一些單詞,由於沒有特別的意義,因而大多數情況下不能成為搜索的關鍵詞,因而創建索引時,這種詞會被去掉而減少索引的大小。
    英語中挺詞(Stop word)如:“the”,“a”,“this”等。
    對於每一種語言的分詞組件(Tokenizer),都有一個停詞(stop word)集合。
    經過分詞(Tokenizer)后得到的結果稱為詞元(Token)
    在我們的例子中,便得到以下詞元(Token):
    “Students”,“allowed”,“go”,“their”,“friends”,“allowed”,“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。
    
第三步:將得到的詞元(Token)傳給語言處理組件(Linguistic Processor)。
    語言處理組件(linguistic processor)主要是對得到的詞元(Token)做一些同語言相關的處理。
    對於英語,語言處理組件(Linguistic Processor)一般做以下幾點:
    1. 變為小寫(Lowercase)。
    2. 將單詞縮減為詞根形式,如“cars”到“car”等。這種操作稱為:stemming
    3. 將單詞轉變為詞根形式,如“drove”到“drive”等。這種操作稱為:lemmatization
    
    Stemming 和 lemmatization的異同:
    相同之處:Stemming和lemmatization都要使詞匯成為詞根形式。
    兩者的方式不同:
        Stemming采用的是“縮減”的方式:“cars”到“car”,“driving”到“drive”。
        Lemmatization采用的是“轉變”的方式:“drove”到“drove”,“driving”到“drive”。
    兩者的算法不同:
        Stemming主要是采取某種固定的算法來做這種縮減,如去除“s”,去除“ing”加“e”,將“ational”變為“ate”,將“tional”變為“tion”。
        Lemmatization主要是采用保存某種字典的方式做這種轉變。比如字典中有“driving”到“drive”,“drove”到“drive”,“am, is, are”到“be”的映射,做轉變時,只要查字典就可以了。
    Stemming和lemmatization不是互斥關系,是有交集的,有的詞利用這兩種方式都能達到相同的轉換。

    語言處理組件(linguistic processor)的結果稱為詞(Term)。
    在我們的例子中,經過語言處理,得到的詞(Term)如下:
 “student”,“allow”,“go”,“their”,“friend”,“allow”,“drink”,“beer”,“my”,“friend”,“jerry”,“go”,“school”,“see”,“his”,“student”,“find”,“them”,“drink”,“allow”。
    也正是因為有語言處理的步驟,才能使搜索drove,而drive也能被搜索出來。

   
第四步:將得到的詞(Term)傳給索引組件(Indexer)。
1. 利用得到的詞(Term)創建一個字典。
2. 對字典按字母順序進行排序。
3. 合並相同的詞(Term)成為文檔倒排(Posting List)鏈表。

 

4.索引的檢索過程

    第一步:用戶輸入查詢語句。
    第二步:對查詢語句進行詞法分析,語法分析,及語言處理。
    1. 詞法分析主要用來識別單詞和關鍵字。
    2. 語法分析主要是根據查詢語句的語法規則來形成一棵語法樹。
    3. 語言處理同索引過程中的語言處理幾乎相同。
    
    第三步:搜索索引,得到符合語法樹的文檔。
    第四步:根據得到的文檔和查詢語句的相關性,對結果進行排序。
    1. 計算權重(Term weight)的過程。
    2. 判斷Term之間的關系從而得到文檔相關性的過程,也即向量空間模型的算法(VSM)。

 

粗略概括:

1.索引過程
    1) 有一系列被索引文件
    2) 被索引文件經過語法分析和語言處理形成一系列詞(Term)。
    3) 經過索引創建形成詞典和反向索引表。
    4) 通過索引存儲將索引寫入硬盤。

2. 搜索過程:
    a) 用戶輸入查詢語句。
    b) 對查詢語句經過語法分析和語言分析得到一系列詞(Term)。
    c) 通過語法分析得到一個查詢樹。
    d) 通過索引存儲將索引讀入到內存。
    e) 利用查詢樹搜索索引,從而得到每個詞(Term)的文檔鏈表,對文檔鏈表進行交,差,並得到結果文檔。
    f) 將搜索到的結果文檔對查詢的相關性進行排序。
    g) 返回查詢結果給用戶。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM