搜索引擎概述


概述
全文搜索就是對文本數據的一種搜索方式,文本數據的都多,可以分為順序搜索法和索引搜索法,,全文檢索使用的是索引搜索法
特點(優勢):

  • 做了相關度排序
  • 對文本中的關鍵字做了高亮顯示
  • 摘要截取
  • 只關注文本,不考慮語義
  • 搜索效果更加精確——基於單詞搜索,比如搜索Java的時候找不到JavaScript,因為它們是不同的兩個單詞

使用場景:

  • 替換數據庫的模糊查詢,提高查詢速度,降低數據庫壓力,增強了查詢效率
  • 數據庫模糊查詢缺點:查詢速度慢,左模糊和全模糊會使索引失效,沒有相關度排序,沒有對文本中關鍵字
  • 做高亮顯示,搜索效果不好
  • 全文檢索是搜索引擎的基礎
  • 只對“指定領域”的網站進行索引和搜索,即垂直搜索
  • 可以在word、pdf等各種各樣的數據格式中檢索內容
  • 其他場合,比如輸入法等

倒排索引
正向索引的結構如下:
“文檔1”的ID > 單詞1:出現次數,出現位置列表;單詞2:出現次數,出現位置列表;…………。
“文檔2”的ID > 此文檔出現的關鍵詞列表。

當用戶在主頁上搜索關鍵詞“華為手機”時,假設只存在正向索引(forward index),那么就需要掃描索引庫中的所有文檔,找出所有包含關鍵詞“華為手機”的文檔,再根據打分模型進行打分,排出名次后呈現給用戶。因為互聯網上收錄在搜索引擎中的文檔的數目是個天文數字,這樣的索引結構根本無法滿足實時返回排名結果的要求所以,搜索引擎會將正向索引重新構建為倒排索引,即把文件ID對應到關鍵詞的映射轉換為關鍵詞到文件ID的映射,每個關鍵詞都對應着一系列的文件,這些文件中都出現這個關鍵詞。
得到倒排索引的結構如下:
“關鍵詞1”:“文檔1”的ID,“文檔2”的ID,…………。
“關鍵詞2”:帶有此關鍵詞的文檔ID列表。

 

 

 創建索引

 

全文檢索的索引創建過程一般有以下幾步:
一些要索引的原文檔(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都要使詞匯成為詞根形式。
  • 兩者的方式不同:
  1. Stemming采用的是“縮減”的方式:“cars”到“car”,“driving”到“drive”。
  2. Lemmatization采用的是“轉變”的方式:“drove”到“drove”,“driving”到“drive”。
  • 兩者的算法不同:
  1. Stemming主要是采取某種固定的算法來做這種縮減,如去除“s”,去除“ing”加“e”,將“ational”變
  2. 為“ate”,將“tional”變為“tion”。
  3. 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”,“schoo
l”,“see”,“his”,“student”,“find”,“them”,“drink”,“allow”。
也正是因為有語言處理的步驟,才能使搜索drove,而drive也能被搜索出來。
將得到的詞(Term)傳給索引組件(Indexer)
索引 組件(Indexer)主要做以下幾件事情:
1. 利用得到的詞(Term)創建一個字典。
在我們的例子中字典如下:

 

 

 2.對字典按字母順序進行排序。

 

 

 3. 合並相同的詞(Term) 成為文檔倒排(Posting List) 鏈表。

 

 

 

在此表中,有幾個定義:

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

所以對詞(Term) “allow”來講,總共有兩篇文檔包含此詞(Term),從而詞(Term)后面的文檔鏈表總共有兩項,第一項表示包含“allow”的第一篇文檔,即1號文檔,此文檔中,“allow”出現了2次,第二項表示包含“allow”的第二個文檔,是2號文檔,此文檔中,“allow”出現了1次。到此為止,

索引已經創建好了,我們可以通過它很快的找到我們想要的文檔。而且在此過程中,我們驚喜地發現,搜索“drive”,“driving”,“drove”,“driven”也能夠被搜到。因為在我們的索引中,“driving”,“drove”,“driven”都會經過語言處理而變成“drive”,在搜索時,如果您輸入“driving”,輸入的查詢
語句同樣經過我們這里的一到三步,從而變為查詢“drive”,從而可以搜索到想要的文檔。
搜索索引
到這里似乎我們可以宣布“我們找到想要的文檔了”。
然而事情並沒有結束,找到了僅僅是全文檢索的一個方面。不是嗎?如果僅僅只有一個或十個文檔包含我們查詢的
字符串,我們的確找到了。然而如果結果有一千個,甚至成千上萬個呢?那個又是您最想要的文件呢?
打開Google吧,比如說您想在微軟找份工作,於是您輸入“Microsoft job”,您卻發現總共有22600000個結果返
回。好大的數字呀,突然發現找不到是一個問題,找到的太多也是一個問題。在如此多的結果中,如何將最相關的
放在最前面呢?

當然Google做的很不錯,您一下就找到了jobs at Microsoft。想象一下,如果前幾個全部是“Microsoft does a good job at software industry…”將是多么可怕的事情呀。
如何像Google一樣,在成千上萬的搜索結果中,找到和查詢語句最相關的呢?
如何判斷搜索出的文檔和查詢語句的相關性呢?
這要回到我們第三個問題:如何對索引進行搜索?
搜索主要分為以下幾步:
用戶輸入查詢語句
查詢語句同我們普通的語言一樣,也是有一定語法的。不同的查詢語句有不同的語法,如SQL語句就有一定的語法。查詢語句的語法根據全文檢索系統的實現而不同。最基本的有比如:AND, OR, NOT等。舉個例子,用戶輸入語句:lucene AND learned NOT Hadoop。
說明用戶想找一個包含lucene和learned然而不包括hadoop的文檔。
對查詢語句進行詞法分析,語法分析,及語言處理
由於查詢語句有語法,因而也要進行語法分析,語法分析及語言處理。
1. 詞法分析主要用來識別單詞和關鍵字。
如上述例子中,經過詞法分析,得到單詞有lucene,learned,hadoop, 關鍵字有AND, NOT。
如果在詞法分析中發現不合法的關鍵字,則會出現錯誤。如lucene AMD learned,其中由於AND拼錯,導致AMD
作為一個普通的單詞參與查詢。
2. 語法分析主要是根據查詢語句的語法規則來形成一棵語法樹。
如果發現查詢語句不滿足語法規則,則會報錯。如lucene NOT AND learned,則會出錯。
如上述例子,lucene AND learned NOT hadoop形成的語法樹如下:

 

 

 

3. 語言處理同索引過程中的語言處理幾乎相同。
如learned變成learn等。
經過第二步,我們得到一棵經過語言處理的語法樹。

 

 

 搜索索引,得到符合語法樹的文檔

此步驟有分幾小步:
1. 首先,在反向索引表中,分別找出包含lucene,learn,hadoop的文檔鏈表。
2. 其次,對包含lucene,learn的鏈表進行合並操作,得到既包含lucene又包含learn的文檔鏈表。
3. 然后,將此鏈表與hadoop的文檔鏈表進行差操作,去除包含hadoop的文檔,從而得到既包含lucene又包含
learn而且不包含hadoop的文檔鏈表。
4. 此文檔鏈表就是我們要找的文檔。

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

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

如何計算文檔和查詢語句的相關性呢?
不如我們把查詢語句看作一片短小的文檔,對文檔與文檔之間的相關性(relevance)進行打分(scoring),分數高的相關性好,就應該排在前面。

那么又怎么對文檔之間的關系進行打分呢?
這可不是一件容易的事情,首先我們看一看判斷人之間的關系吧。
首先 看一個人,往往有很多要素 ,如性格,信仰,愛好,衣着,高矮,胖瘦等等。
其次 對於人與人之間的關系,不同的要素重要性不同 ,性格,信仰,愛好可能重要些,衣着,高矮,胖瘦可能就不那么重要了,所以具有相同或相似性格,信仰,愛好的人比較容易成為好的朋友,然而衣着,高矮,胖瘦不同的人,也可以成為好的朋友。
因而判斷人與人之間的關系,首先要找出哪些要素對人與人之間的關系最重要 ,比如性格,信仰,愛好。其次要判斷兩個人的這些要素之間的關系 ,比如一個人性格開朗,另一個人性格外向,一個人信仰佛教,另一個信仰上帝,一個人愛好打籃球,另一

個愛好踢足球。我們發現,兩個人在性格方面都很積極,信仰方面都很善良,愛好方面都愛運動,因而兩個人關系應該會很好。
我們再來看看公司之間的關系吧。
首先 看一個公司,有很多人組成,如總經理,經理,首席技術官,普通員工,保安,門衛等。
其次對於公司與公司之間的關系,不同的人重要性不同 ,總經理,經理,首席技術官可能更重要一些,普通員工,保安,門衛可能較不重要一點。所以如果兩個公司總經理,經理,首席技術官之間關系比較好,兩個公司容易有比較好的關系。然而一位普通

員工就算與另一家公司的一位普通員工有血海深仇,怕也難影響兩個公司之間的關系。因而判斷公司與公司之間的關系,首先要找出哪些人對公司與公司之間的關系最重要 ,比如總經理,經理,首席技術官。其次要判斷這些人之間的關系 ,不如兩家公司的

總經理曾經是同學,經理是老鄉,首席技術官曾是創業伙伴。我們發現,兩家公司無論總經理,經理,首席技術官,關系都很好,因而兩家公司關系應該會很好。
分析了兩種關系,下面看一下如何判斷文檔之間的關系 了。
首先,一個文檔有很多詞(Term)組成 ,如search, lucene, full-text, this, a, what等。
其次對於文檔之間的關系,不同的Term重要性不同 ,比如對於本篇文檔,search, Lucene, full-text就相對重要一些,this, a , what可能相對不重要一些。所以如果兩篇文檔都包含search, Lucene,fulltext,這兩篇文檔的相關性好一些,然而就算一篇文檔包含

this, a, what,另一篇文檔不包含this, a, what,也不能影響兩篇文檔的相關性。因而判斷文檔之間的關系,首先找出哪些詞(Term)對文檔之間的關系最重要,如search, Lucene, fulltext。然后判斷這些詞(Term)之間的關系。找出詞(Term) 對文檔的重要性的過程

稱為計算詞的權重(Term weight) 的過程。計算詞的權重(Term weight)表示此詞(Term)在此文檔中的重要程度,越重要的詞(Term)有越大的權重(Term weight),因而在計算文檔之間的相關性中將發揮更大的作用。判斷詞(Term) 之間的關系從而得到文檔相關性的

過程應用一種叫做向量空間模型的算法(Vector Space Model) 。
下面仔細分析一下這兩個過程:
1. 計算權重(Term weight)的過程。
影響一個詞(Term)在一篇文檔中的重要性主要有兩個因素:

  • Term Frequency (tf):即此Term在此文檔中出現了多少次。tf 越大說明越重要。
  • Document Frequency (df):即有多少文檔包含次Term。df 越大說明越不重要。

容易理解嗎?詞(Term)在文檔中出現的次數越多,說明此詞(Term)對該文檔越重要,如“搜索”這個詞,在本文檔中出現的次數很多,說明本文檔主要就是講這方面的事的。然而在一篇英語文檔中,this出現的次數更多,就說明越重要嗎?不是的,這是由第二個因素進

行調整,第二個因素說明,有越多的文檔包含此詞(Term), 說明此詞(Term)太普通,不足以區分這些文檔,因而重要性越低。

這也如我們程序員所學的技術,對於程序員本身來說,這項技術掌握越深越好(掌握越深說明花時間看的越多,tf越大),找工作時越有競爭力。然而對於所有程序員來說,這項技術懂得的人越少越好(懂得的人少df小),找工作越有競爭力。人的價值在於不可替代

性就是這個道理。道理明白了,我們來看看公式:

 

 

 

這僅僅只term weight計算公式的簡單典型實現。實現全文檢索系統的人會有自己的實現,Lucene就與此稍有不
同。
2. 判斷Term之間的關系從而得到文檔相關性的過程,也即向量空間模型的算法(VSM)。
我們把文檔看作一系列詞(Term),每一個詞(Term)都有一個權重(Term weight),不同的詞(Term)根據自己在文檔中的權重來影響文檔相關性的打分計算。
於是我們把所有此文檔中詞(term)的權重(term weight) 看作一個向量。
Document = {term1, term2, …… ,term N}
Document Vector = {weight1, weight2, …… ,weight N}
同樣我們把查詢語句看作一個簡單的文檔,也用向量來表示。
Query = {term1, term 2, …… , term N}
Query Vector = {weight1, weight2, …… , weight N}
我們把所有搜索出的文檔向量及查詢向量放到一個N維空間中,每個詞(term)是一維。如圖:

 

 

我們認為兩個向量之間的夾角越小,相關性越大。所以我們計算夾角的余弦值作為相關性的打分,夾角越小,余弦值越大,打分越高,相關性越大。有人可能會問,查詢語句一般是很短的,包含的詞(Term)是很少的,因而查詢向量的維數很小,而文檔很長,包含
詞(Term)很多,文檔向量維數很大。你的圖中兩者維數怎么都是N呢?在這里,既然要放到相同的向量空間,自然維數是相同的,不同時,取二者的並集,如果不含某個詞(Term)時,則權重(Term Weight)為0。
相關性打分公式如下:

 

 舉個例子,查詢語句有11個Term,共有三篇文檔搜索出來。其中各自的權重(Term weight),如下表格。

 

 於是計算,三篇文檔同查詢語句的相關性打分分別為:

 

 

於是文檔二相關性最高,先返回,其次是文檔一,最后是文檔三。

到此為止,我們可以找到我們最想要的文檔了。
說了這么多,其實還沒有進入到Lucene,而僅僅是信息檢索技術(Information retrieval)中的基本理論,然而當我
們看過Lucene后我們會發現,Lucene是對這種基本理論的一種基本的的實踐。所以在以后分析Lucene的文章中,
會常常看到以上理論在Lucene中的應用。
在進入Lucene之前,對上述索引創建和搜索過程所一個總結,如圖:
此圖參照http://www.lucene.com.cn/about.htm 中文章《開放源代碼的全文檢索引擎Lucene》

1. 索引過程:
1) 有一系列被索引文件
2) 被索引文件經過語法分析和語言處理形成一系列詞(Term) 。
3) 經過索引創建形成詞典和反向索引表。
4) 通過索引存儲將索引寫入硬盤。
2. 搜索過程:
a) 用戶輸入查詢語句。
b) 對查詢語句經過語法分析和語言分析得到一系列詞(Term) 。
c) 通過語法分析得到一個查詢樹。
d) 通過索引存儲將索引讀入到內存。
e) 利用查詢樹搜索索引,從而得到每個詞(Term) 的文檔鏈表,對文檔鏈表進行交,差,並得到結果文檔。
f) 將搜索到的結果文檔對查詢的相關性進行排序。
g) 返回查詢結果給用戶。
Lucene和ElasticSearch
lucene:全文搜索工具包,依賴於java,不適用於集群環境
ES:全文搜索服務器,基於lucene,采用Rest HTTP調用方式,對集群支持較好
分詞器
WhitespaceAnalyzer
僅僅是去掉了空格,沒有其他任何操作,不支持中文。
SimpleAnalyzer
講除了字母以外的符號全部去除,並且講所有字符變為小寫,需要注意的是這個分詞器同樣把數據也去除了,同樣不支持中文。
StopAnalyzer
這個和SimpleAnalyzer類似,不過比他增加了一個的是,在其基礎上還去除了所謂的stop words,比如the, a, this這些。這個也是不支持中文的。
StandardAnalyzer
英文方面的處理和StopAnalyzer一樣的,對中文支持,使用的是單字切割。
CJKAnalyzer
這個支持中日韓,前三個字母也就是這三個國家的縮寫。這個對於中文基本上不怎么用吧,對中文的支持很爛,它是用每兩個字作為分割,分割方式個人感覺比較奇葩,我會在下面比較舉例。
SmartChineseAnalyzer
中文的分詞。比較標准的中文分詞,對一些搜索處理的並不是很好



 

 


免責聲明!

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



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