現在人們的網絡生活已經離不開搜索了,遇到不懂的問題,想知道的事情,搜索一下,就知道答案。
在app中,最常見的搜索情景就是搜索用戶。只有幾百,幾千的用戶量時,可以直接用用like這樣的模糊查詢,但是,如果數據有幾百萬,甚至上千萬的時候,一次like查詢數據庫就堵了。到了一定量級的時候,不得不考慮使用專門的搜索技術。
1. 一個簡單的搜索例子
有三行數據:
(1)近2周8成股民虧損超10%。
(2)滿倉中國夢。
(3)股民兩天虧一套三居。
例如,有個需求,從上面的3行數據中,把包含“股民”這個關鍵詞的數據找出來。
按照一般的做法,就是分別查找上面的每一行數據:
第一行數據從頭到尾查找一次,發現有“股民”這個關鍵詞。
第二行數據從頭到尾查找一次,沒有有“股民”這個關鍵詞。
第三行數據從頭到尾查找一次,發現有“股民”這個關鍵詞。
根據查找結果,第一,第三行數據包含“股民”這個關鍵詞。
2. 搜索技術的基本原理
按照上面的過程,每次查找,都需要把每行數據從頭到尾查一次。
如果需要從上百萬,千萬的數據中查找一個關鍵詞,讀者可以想象一下效率有多低。
我們看一下搜索引擎的例子,在搜索引擎搜索“股民”這個關鍵詞的結果:
圖1
在搜索引擎的搜索結果中,是直接顯示了所有包含“股民”這個關鍵字的數據。
它是怎么做到在海量的信息中,快速搜索中包含關鍵字的信息的呢?
實現搜索的關鍵,就是分詞和倒序索引。
如果我們知道每行數據中包含多少個關鍵字,然后建立一個映射表,把每個關鍵字出現在哪行數據中記錄下來,搜索就變得很輕松。當知道一個關鍵字的時候,只需要查找這個映射表,找到這個關鍵詞,根據這個關鍵詞建立的映射關系就能查到包含這個關鍵詞的數據。
知道每行數據中包含多少個關鍵字的過程,就是分詞。這里有個問題,什么是關鍵字?
關鍵字,其實就是一個詞語或句子,例如,當我有需要的時候,“股民”可以是搜索的關鍵字,但是,“股”也可以是搜索的關鍵字,“民”也可以是搜索的關鍵字。什么是關鍵字,要看使用者的需求。因此,為了能准確分析出一行數據到底包含多少個關鍵字,就需要一個包含了所有詞語或句子的詞典,用來分析數據中有什么關鍵字。
建立一個映射表,把每個關鍵字出現在哪行數據中記錄下來,這個過程就是建倒序搜引。
下面舉個實際的例子,看看是怎么分詞和建立倒序索引。
還是用回上面舉例的三行數據,左邊的是數據的編號,右邊的是數據的內容。
(1)近2周8成股民虧損超10%。
(2)滿倉中國夢。
(3)股民兩天虧一套三居。
首先,把分析上面每行數據包含多少個關鍵詞(這里為了簡化分詞過程,沒有把每個漢字或數字當成一個關鍵詞,例如,” 民”應該是個關鍵詞,但為了簡化分詞,沒有當成一個關鍵詞),結果如表1所示。
表1
下面根據表1的結果建立一個映射表表2,把每個關鍵字出現在哪行數據中記錄下來
表2
用上面的表2,我們很容易得知,“股民”這個關鍵詞在數據1,3中出現過。如果需要知道“中國”這個關鍵詞出現在哪,通過查找表2也很容易得知出現在數據2中。
在這么幾行數據中,還不能體驗到倒序索引的高效。如果數據量到了上百萬,千萬,甚至上億,倒序索引的效率就非常明顯了。歸根到底,這種數據結構就是為了實現快速搜索也建立的。
再進一步,表2的右側,除了記錄關鍵詞出現在哪行數據中,還能記錄在某行數據中出現的頻率,出現的位置等信息,如果有興趣繼續深入了解搜索引擎的技術,可閱讀《這就是搜索引擎:核心技術詳解》(張俊林著),這篇文章只是簡單介紹搜索引擎的基本原理。
3. 常見的開源搜索軟件介紹
搜索技術一點都不簡單,如果要我們從頭開始做,不知道要到哪年哪月才能用給app用上搜索功能。幸好,大牛們已經為我們開源大量的搜索軟件,只要我們會使用這些搜索軟件提供的api,就能給app后台整合搜索技術。下面簡單介紹一下常見的搜索軟件。
(1) Lucene
Lucene是apache軟件基金會4 jakarta項目組的一個子項目,是一個開放源代碼的全文檢索引擎工具包,即它不是一個完整的全文檢索引擎,而是一個全文檢索引擎的架構,提供了完整的查詢引擎和索引引擎,部分文本分析引擎(英文與德文兩種西方語言)。
Lucene的目的是為軟件開發人員提供一個簡單易用的工具包,以方便的在目標系統中實現全文檢索的功能,或者是以此為基礎建立起完整的全文檢索引擎。Lucene是一套用於全文檢索和搜尋的開源程式庫,由Apache軟件基金會支持和提供。Lucene提供了一個簡單卻強大的應用程式接口,能夠做全文索引和搜尋。在Java開發環境里Lucene是一個成熟的免費開源工具。就其本身而言,Lucene是當前以及最近幾年最受歡迎的免費Java信息檢索程序庫。
(2) Solr
Solr是一個高性能,采用Java5開發,基於Lucene的全文搜索服務器。同時對其進行了擴展,提供了比Lucene更為豐富的查詢語言,同時實現了可配置、可擴展並對查詢性能進行了優化,並且提供了一個完善的功能管理界面,是一款非常優秀的全文搜索引擎。它對外提供類似於Web-service的API接口。用戶可以通過http請求,向搜索引擎服務器提交一定格式的XML文件,生成索引;也可以通過Http Get操作提出查找請求,並得到XML格式的返回結果。
(3) Elasticsearch
ElasticSearch是一個基於Lucene的搜索服務器。它提供了一個分布式多用戶能力的全文搜索引擎,基於RESTful web接口。Elasticsearch是用Java開發的,並作為Apache許可條款下的開放源碼發布,是第二流行的企業搜索引擎。
(4) Sphinx
Sphinx是一個基於SQL的全文檢索引擎,可以結合MySQL,PostgreSQL做全文搜索,它可以提供比數據庫本身更專業的搜索功能,使得應用程序更容易實現專業化的全文檢索。Sphinx特別為一些腳本語言設計搜索API接口,如PHP,Python,Perl,Ruby等,同時為MySQL也設計了一個存儲引擎插件。
(5) Coreseek
Coreseek 是一款中文全文檢索/搜索軟件,以GPLv2許可協議開源發布,基於Sphinx研發並獨立發布,專攻中文搜索和信息處理領域,適用於行業/垂直搜索、論壇/站內搜索、數據庫搜索、文檔/文獻檢索、信息檢索、數據挖掘等應用場景,用戶可以免費下載使用。
Coreseek曾經在本人架構過兩個app后台深度使用過,配置簡單,性能高效,整合了Sphinx和中文分詞,快速完成了搜索模塊的開發。但最大的缺點是穩定版不支持實時索引,測試版是支持了,但沒在生產環境中用過。
Coreseek的原理如下圖3所示:
圖2
Coreseek有兩個核心模塊 Indexer和Search。
Indexer: 負責從mysql中拉取數據源,把數據源分詞,建立索引
Search:搜索模塊
整個工程的流程如下:
1. Indexer模塊從mysql中拉取數據
2. Indexer模塊把數據經過中文分詞,建立索引
3. 客戶端向Search模塊發起搜索請求
4. Seach模塊查找索引中的數據
5. Seach模塊得到索引中符合要求的數據的id等數據
6. 把數據返回給客戶端
另外,有個小小的經驗分享,搜索的時候,有的用戶直接通過輸入拼音來代替漢字的,如下圖2:
圖3
這種情況,就是要在記錄關鍵字的同時,也要記錄下關鍵字的拼音,把拼音也建索引,就能實現用拼音搜索。
參考資料:
1. http://baike.baidu.com/link?url=rNBW3tzH-oJYeBoPSUvWZPGz-stIkE5zFQsjAtV234HFFPJKyeyr3dJjJrbZKRSCBg2NGZv-lA7DFqHF5XBEoq
4. http://www.coreseek.cn/