用GO語言實現一個簡單的搜尋引擎

來源:互聯網
上載者:User

標籤:redis   搜尋引擎   資料庫   資訊檢索   go語言   

用GO語言實現一個簡單的搜尋引擎

項目地址是:https://github.com/wyh267/FalconEngine

對搜尋引擎感興趣的可以去看看這本書,比較淺並且也比較完整的介紹了一個搜尋引擎的全部機能。

我的這個搜尋引擎未經處理資料是MySql資料庫的,大家可以根據需要進行二次開發,用來支援其他資料庫或者本地檔案,Detail檔案是儲存在Redis資料庫中,同樣這部分也可以根據自己的需要二次開發,使用本地檔案或者其他資料庫,倒排索引和正排索引本機存放區的時候使用的json格式,比較耗磁碟,第一版暫時這樣了吧,後續再做最佳化。

使用方法依賴以下幾個庫
  • github.com/outmana/log4jzl log檔案
  • github.com/ewangplay/config 設定檔解析
  • github.com/go-sql-driver/mysql mysql驅動
  • github.com/garyburd/redigo/redis Redis驅動
  • github.com/huichen/sego 分詞器,作者首頁非常感謝他的分析器,他首頁上也有個搜尋引擎,沒看具體實現,大家感興趣可以去看看。
編譯
  • 直接運行install.sh
運行
  • 從github.com/huichen/sego擷取分詞的字典檔案
  • 運行索引器,會將索引檔案產生到index目錄下

bin/FalconEngine -mode=build

  • 運行搜尋器

bin/FalconEngine -mode=search

基本概念

以下幾個概念需要理解,如果完全不瞭解的話,還需要自己稍微百度一下:倒排索引正排檔案Detail檔案全量索引增量索引雜湊函數DocId

基礎資料結構

搜尋引擎首先並不神秘,基礎的資料結構就那麼幾個,定了以後後面就是在上面添磚加瓦了。

假如有下面五個文檔需要進行搜尋

文檔編號 內容
1 你好,搜尋引擎
2 搜尋引擎有一條資料
3 你好,有一條測試資料
倒排索引

倒排索引是搜尋引擎基礎中的基礎,主要的檢索都是從倒排索引開始的,所以,首先,設計一個倒排索引的資料結構是所有搜尋引擎的基礎。

搜尋引擎的基礎是DocId,也就是文檔ID,DocId是唯一的並且是連續的,而倒排索引就是一組DocId鏈表,每個鏈表對應一個關鍵詞。

上面的文檔建立號倒排索引的基礎結構如

關鍵詞 文檔編號
你好 1,3
搜尋引擎 1,2
資料 2,3
有一條 2,3
測試 3

所以,當我們檢索資料這個詞的時候能迅速知道在文檔23有這條資料,就能進行檢索了。

是不是很簡單,關鍵問題是檢索資料的時候,如何能迅速定位到第三行資料,這裡就用到雜湊表了,所以,一個完整的倒排包括兩部分,一部分是上面的這個表,第二個是一個雜湊表,通過這個雜湊表能知道資料這個詞的下標為3,從而找到2,3這兩個文檔。

雜湊表的具體實現就不詳細展開了,雜湊表有很多種實現方式,並且雜湊函數也有很多種實現方式,總之,對於一個關鍵詞的定位
- 首先,通過計算這個關鍵詞的hash,得到它的下標
- 然後,尋找倒排索引的下標,得到文檔ID的鏈表

在代碼的InvertIndex.go中是倒排索引的資料結構,StringIndexDic.go是關鍵詞的雜湊表,這兩個檔案產生的資料都會序列化成json檔案儲存體下來。

正排索引

正排索引相對倒排就簡單多了,實際上就是一個字典檔案,key是DocId,value是這個DocId對應的內容,主要用來做結果集的過濾,所謂倒排檢索,正排過濾,什麼情境需要這樣的東西呢?下面的情境你肯定經曆過。

你在一個某東的網站搜尋運動鞋,肯定出來一堆鞋子,但是你只想看nike的鞋子,這時候你可以再運動鞋後面加上Nike,搜尋nike運動鞋,但是結果不一定準,因為並不是每個nike的鞋子的標題上都會寫上nike,這時候就需要用到正排了,他會把nike鞋子給你過濾出來。

正排索引就是一個數組,數組的下標就是DocId,檔案中的NumberProfile.goTextProfile.go是具體的實現檔案

Detail檔案

Detail檔案使用的是Redis實現的,沒有具體的資料結構,實際上就是以主鍵ID為key來實現的。

累加式更新

累加式更新使用的是掃描mysql中的一個last_modify_time欄位,擷取資料,然後和redis中的資料進行對比,如果更新了就添加到索引中,添加索引按照如下的步驟進行

  • 如果是正排欄位更新,並且不是新增的資料,只是原來的資料修改

    • 直接更新DocId對應下標的資料
  • 如果是正排欄位更新,但是是新增的資料

    • 新增一個DocId並添加到正排檔案的後面
  • 如果是倒排欄位更新

    • 將原始的DocId從BitMap中刪除
    • 新增一個DocId並添加到倒排檔案的後面

因為DocId是連續的,倒排欄位更新的話,要修改倒排鏈表,而目前的倒排鏈表是數組的,所以直接建立一個BitMap,將對應的DocId刪除,後續改成鏈表形式的話,可以動態刪除。

累加式更新使用的一個go的協程來做的,掃描的是資料庫欄位,後續可以改成從kafka擷取資料或者其他方式擷取累加式更新

資料檢索

資料檢索分成以下幾個步驟

  • 根據關鍵詞從倒排索引中擷取DocId鏈,有多個關鍵詞的時候求交集
  • 通過BitMap過濾掉已經刪除的DocId
  • 最後得到的DocId按照正排檔案的條件進行過濾操作,擷取最終的DocId鏈
  • 通過DocId反查出文檔的真實ID,並通過Redis擷取文檔的詳細資料用於顯示

檔案中的IndexSet.go主要實現了上述步驟

待續。。。。。。。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

用GO語言實現一個簡單的搜尋引擎

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.