Lucene全文檢索基本原理


    一、總論

    Lucene是一個高效的、基於Java的全文檢索庫。

    所以在了解Lucene之前要了解一下全文檢索的概念。

    在存入數據庫中的數據我們分為兩類:結構化數據非結構化數據

    · 結構化數據 :指有具體的格式或者有限長度的數據,如數據庫,元數據等。

    · 非結構化數據 :指不定長或無固定格式的數據,如郵件,word文檔等。

    還有的是第三種數據格式:半結構化數據、如xml,html等,當根據需求可按結構化數據來處理、也可以抽出純文本按非結構數據來處理。

    對非結構化數據的叫法又叫全文數據。

    按照對數據的分類,搜索也有兩種:

    對結構化數據搜索:如對數據庫的搜索,用sql語句。再如對數據源的搜索,如利用windows搜索對文件名、類型、修改時間進行搜索等等。

    對非結構化數據的搜索:如利用windows的搜索也可以搜索文件內容,linux下的grep命令、再如Google或者百度對大量數據的搜索。

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

    1.順序掃描法:從字面上理解就是把要搜索的所有數據全部進行比較,找到需要的內容。

       特點:算法簡單,流程簡單。

       缺點:對於大量數據操作時效率極低。

    2.全文檢索:通過對非結構化數據的部分信息進行提取,然后進行組織,使其獲得一定的結構,然后對此有一定結構的數據進行搜索,從而達到搜索速度的提高。而從非結構化數據提取的信息我們就叫做索引。

   理解全文檢索:比如字典,字典的拼音就是索引,我們可以通過索引查找相應的漢字,從而不需要對字典的所有漢字進行一個一個的查找。

   那么建立索引就對非結構化查詢來說至關重要。

   二:初識索引

   Lucene檢索過程

    

     圖中過程分為兩部分:一部分是收集數據另一部分是提供搜索服務。

     但是它們都會用到一個東西Index索引庫。

     過程一:收集數據建立索引庫

     將現實中的結構化數據和非結構化數據進行提取信息,創建索引的過程。

     那么索引如何創建呢?

     首先我們要知道索引是什么,才能創建索引。

     索引使我們解決順序掃描效率慢的一個解決方法,因為順序掃描需要對文件依次進行檢索,從第一個到最后一個,那么我們有什么辦法讓它去找有該內容的文件呢?所以索引是我們標記該文件存儲內容的一個東西。

      我們現在要檢索一個文件夾內的文件包含指定字符串,即已知字符串求文件,這個是比較復雜的,我們不知道哪個文件包含此字符串,需要檢索所有的文件。那么反過來我們要找該文件包含哪些字符串,即已知文件求字符串,就簡單些,因為我們知道指定的文件,掃描該文件即可找到所有字符串。

      那么我們就將索引建立為字符串到文件的映射,就可以大大提高檢索效率。由於從字符串到文件的映射是文件到字符串的反向過程,於是保存這種信息的索引被稱為反向索引

      反向索引的保存信息一般如下:

      假如我的文檔集合里面有100篇文檔,為了方便表示,我們為文檔做編號,從1-100,得到下面的結構。

       

        左邊保存的是一系列字符串,稱為詞典

        每個字符串都是指向包含此字符串的文檔鏈表,此文檔鏈表稱為倒排表

        有了索引,便使保存的信息和要索引的信息一致,可以大大加快索引的速度。

        過程二:獲取查詢信息對索引庫進行檢索

        比如說,我們要尋找既包含字符串“Lucene”又包含字符串“solr”的文檔,我們只需要以下幾步:

        1.取出包含字符串“Lucene”的文檔鏈表。

        2.取出包含字符串“solr”的文檔鏈表。

        3.通過合並鏈表,找出既包含“Lucene”又包含“solr”的文件。

         

         這就是全文檢索的過程。

         索引有一個好處就是創建索引只需要一次,重復檢索不需要每次創建。

         三:創建索引

         第一步:需要索引的文檔(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);

         分詞組件:

         1.將文檔分成一個一個單獨的單詞。

         2.去除標點符號。

         3.去除停詞(Stop word)。

         所謂的停詞就是一種語言中最普通的一些單詞,由於沒有特別的意義,因而大多數情況下不能作為搜索的關鍵字,因而創建索引時會被去掉,而減小索引的大小。(this,a,the等)

        對於每一種語言都有一個停詞集合。

        經歷過分詞(Tokenizer)后得到的結果稱為詞元(Token)。

       在我們的例子中,便得到以下詞元:  “Students”,“allowed”,“go”,“their”,“friends”,“allowed”,“drink”,“beer”,“My”,“friend”,“Jerry”,“went”,“school”,“see”,“his”,“students”,“found”,“them”,“drunk”,“allowed”。

        第三步:將得到的詞元傳給語言處理組件(Linguistic Processor)。

        語言處理組件主要是對詞元做一些同語言相關的處理。

        1.變為小寫。

        2.將單詞縮減為詞根。如“cars”到“car”等。這種過程稱為:stemming。

        3.將單詞縮減為詞根形式。如“drove”到“drive”等。這種操作被稱為:lemmatization。

         兩者從方式和算法上是不同的。stemming多為替換刪減,而lemmatization則需要依賴單獨的詞典。

         語言處理組件得到的結果稱為詞(Term)。

        在我們的例子中,經過語言處理,得到的詞(Term)如下:

“student”,“allow”,“go”,“their”,“friend”,“allow”,“drink”,“beer”,“my”,“friend”,“jerry”,“go”,“school”,“see”,“his”,“student”,“find”,“them”,“drink”,“allow”。

        第四步:將得到的詞(Term)傳給索引組件。

        1.利用得到的詞創建一個字典。

         

              2.對字典進行排序

                

          3.合並相同的詞成為文檔倒排鏈表。

          

 

              在表中,有 幾個定義:

                   Document Frequency 即文檔頻次,表示總共有多少文件包含此詞(Term)。

                   Frequency即詞頻率,表示此文件中包含了幾個此詞(Term)。

             到此索引創建成功。

             四、檢索索引

             接下來就是用戶輸入查詢條件進行對索引的檢索了,然后將文件返回給用戶。

             比如使用Google進行數據檢索時,通常我們能的到幾億份文件,那么如何才能得到我們想要的數據呢?

           這時一個詞就可以解決:相關性

           相關性越高的文件對我們來說越重要,那么如何判斷相關性就是把數據檢出的關鍵。

           檢出數據的步驟:

           第一步:用戶輸入查詢語句。

           查詢語句一般都是有格式的,比如sql語句。

           而查詢語句也是有一定的規則。比如AND,OR,NOT等。

           舉個例子,用戶輸入語句:Lucene AND solr NOT hadoop。

           就是說用戶想要查詢一個包含Lucene和solr但是不包含hadoop的文件。

           第二步:對查詢語句進行詞法分析,語句分析,及語言處理。

           1.詞法分析主要是用來識別關鍵字和單詞。

           2.語法分析主要是分局查詢語句的語法規則來形成一顆語法樹。

              通過樹形結構排除不包含的信息。

               

                3.語言處理跟索引建立的過程基本一樣。

                

        第三步:搜索索引,得到符合語法樹的文檔。

         此步驟有分幾小步:

  1. 首先,在反向索引表中,分別找出包含lucene,learn,hadoop的文檔鏈表。

  2. 其次,對包含lucene,learn的鏈表進行合並操作,得到既包含lucene又包含learn的文檔鏈表。

  3. 然后,將此鏈表與hadoop的文檔鏈表進行差操作,去除包含hadoop的文檔,從而得到既包含lucene又包含learn而且不包含hadoop的文檔鏈表。

  4. 此文檔鏈表就是我們要找的文檔。

         第四步:根據得到的文檔和查詢語句的相關性,對結果進行排序。

         雖然在上一步,我們得到了想要的文檔,然而對於查詢結果應該按照與查詢語句的相關性進行排序,越相關者越靠前。

         如何計算文檔和查詢語句的相關性呢?

         這個我就不會了。。。你們看看原作者寫的吧!

         http://mp.weixin.qq.com/s/3z8qZeg_sTVw2_6hLkUdUw

         請關注Java團長,從他那里學到了很多,這篇文章手打的基本都看會了。

 


免責聲明!

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



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