全文搜索是指計算機索引程序經過掃描文章中的每個詞,對每個詞創建一個索引,指明該詞在文章中出現的次數和位置,當用戶查詢時,檢索程序就根據事先創建的索引進行查找,並將查找的結果反饋給用戶的檢索方式。這個過程相似於經過字典中的檢索字表查字的過程。全文搜索搜索引擎數據庫中的數據。 java
全文搜索的過程主要分爲兩個部分,索引的創建以及索引的搜索。 node
國內外的全文搜索經常使用的檢索模型主要有向量模型,布爾模型等。 算法
布爾模型 數據庫
布爾模型是第一個信息檢索的模型,可能也是最受爭論的模型。它利用布爾運算符鏈接各個檢索詞,而後由計算機進行邏輯運算,找出所需信息的一種檢索方法。布爾定義了三種基本操做:AND,OR和NOT。 負載均衡
機率檢索模型 框架
可能是創建在相關性理論基礎上,基於對相關性的不一樣理解而創建了不一樣的機率檢索模型,並且由此導出不一樣的排序輸出原則。能夠說相關性原理及排序原理是機率檢索模型的理論核心。 分佈式
向量模型 性能
向量空間模型(Vector Space Model,VSM)在上世紀70年代由信息檢索領域奠定人Salton教授提出來,併成功地應用於著名的SMART文本檢索系統。把對文本內容的處理簡化爲向量空間中的向量運算,它以空間上的類似度表達語義的類似度,直觀易懂。當文檔被表示爲文檔空間的向量,就能夠經過計算向量之間的類似性來度量文檔間的類似性。向量空間模型的數學模型基礎是餘弦類似性理論,下面先從數學推導上認識餘弦類似性理論。 搜索引擎
在同一個N維空間中存在兩個非零向量A和B: spa
向量A記做
向量B記做
向量A和B的夾角爲,那麼由夾角公式可得:
夾角餘弦值是與向量的長度無關的,僅僅與向量的指向方向相關。當向量A和B向量方向徹底相同時,那麼兩個向量之間的夾角爲0,
;當A向量和B向量方向徹底相反時,那麼兩個向量之間的夾角爲180度,
;當A向量和B向量互相垂直時,即夾角爲90度,
。0度角的餘弦值是1,而其餘任何角度的餘弦值都不大於1,而且其最小值是-1,從而經過兩個向量之間的角度的餘弦值肯定兩個向量是否大體指向相同的方向。用向量夾角餘弦值來衡量類似度:
餘弦類似度一般用於正空間,所以給出的值爲0到1之間。以下圖所示,假設兩個文檔doc1和doc2,doc1和doc2在向量空間中分別用向量和向量
來表示。
關鍵詞查詢向量爲,
和
的夾角爲
,
和
的夾角爲
。經過計算
得出查詢向量和doc1之間的類似性:
計算得出查詢向量和doc2之間的類似性:
比較和
的大小能夠得出文檔1和文檔哪一個和查詢關鍵詞相關度更大。
Lucene的評分公式
向量空間模型是信息檢索領域中一種成熟和基礎的檢索模型。這種方法以3維空間中的向量做爲類比,維度就是作好索引的term,好比這裏以3個主要的關鍵詞百度、招聘、java爲三個維度,經過文檔在各個維度上的權重,每一個文檔以及查詢都會在空間中有一個向量,直觀的看起來,兩個向量越類似,則他們的夾角越小,因此cos值越大,則兩個向量越類似,同理即可以將3維空間推廣到多維空間去。
用向量空間模型,便將相關性轉化爲類似性,根據點積和模的定義,能夠獲得下式:
如今的問題就變成,如何求得每一個維度上的term在文檔中的權重,在向量空間模型中,特徵權重的計算框架是TF*IDF框架,這裏TF(Term Frequency)就是term在文檔中的詞頻,TF值越大,說明該篇文檔相對於這個term來講更加劇要,所以權重應該更高;而IDF(Inverse Document Frequency)則是term在整個文檔集中佔的比重。IDF的主要思想是,若是包含詞條t的文檔越少,IDF越大,則說明詞條t具備很好的類別區分能力。
若是一個詞越常見,那麼分母就越大,逆文檔頻率就越小越接近0。分母之因此要加1,是爲了不分母爲0。
能夠看到,TF-IDF與一個詞在文檔中的出現次數成正比,與該詞在整個語言中的出現次數成反比。
有了以上基礎以後能夠對Lucene的公式進行簡單的推導
,
須要注意的是隻有當詞都存在於q和d中纔不爲0。
實際上當不是標準公式的時候,最終的得分也就不是兩個向量的餘弦了。這裏不是lucene的最終公式,而是給出了大致的架子。
Lucene中的完整打分公式:
coord(q,d):協調因子,它的計算是基於文檔d中所包含的全部可供查詢的詞條數量
queryNorm:在給出每一個查詢條目的方差和後,計算某查詢的標準化值
tf:單詞t在文檔d中出現的詞頻
idf:單詞t在文檔集中的比重
t.getBoost():在搜索過程當中影響評分的參數
norm(t,d):字段的標準化值
Lucene索引創建及索引搜索
非結構化數據中所存儲的信息是每一個文件包含哪些字符串,也即已知文件,欲求字符串相對容易,也便是從文件到字符串的映射。而咱們想搜索的信息是哪些文件包含此字符串,也即已知字符串,欲求文件,也即從字符串到文件的映射。二者偏偏相反。因而若是索引總可以保存從字符串到文件的映射,則會大大提升搜索速度。
因爲從字符串到文件的映射是文件到字符串映射的反向過程,因而保存這種信息的索引稱爲反向索引 。
反向索引的所保存的信息通常以下:
假設個人文檔集合裏面有100篇文檔,爲了方便表示,咱們爲文檔編號從1到100,獲得下面的結構
左邊保存的是一系列字符串,稱爲詞典。每一個字符串都指向包含此字符串的文檔(Document)鏈表,此文檔鏈表稱爲倒排表 (Posting List)。有了索引,便使保存的信息和要搜索的信息一致,能夠大大加快搜索的速度。好比說,咱們要尋找既包含字符串"lucene"又包含字符串"solr"的文檔,咱們只須要如下幾步:
1. 取出包含字符串"lucene"的文檔鏈表。
2. 取出包含字符串"solr"的文檔鏈表。
3. 經過合併鏈表,找出既包含"lucene"又包含"solr"的文件。
看到這個地方,有人可能會說,全文檢索的確加快了搜索的速度,可是多了索引的過程,二者加起來不必定比順序掃描快多少。的確,加上索引的過程,全文檢索不必定比順序掃描快,尤爲是在數據量小的時候更是如此。而對一個很大量的數據建立索引也是一個很慢的過程。然而二者仍是有區別的,順序掃描是每次都要掃描,而建立索引的過程僅僅須要一次,之後即是一勞永逸的了,每次搜索,建立索引的過程沒必要通過,僅僅搜索建立好的索引就能夠了。這也是全文搜索相對於順序掃描的優點之一:一次索引,屢次使用。
索引結構以下
有了單機的Lucene知識基礎,能夠再深刻了解一下分佈式的ElasticSearch。Elasticsearch是一個基於Apache Lucene的分佈式可擴展的實時搜索和分析引擎。
Elasticsearch在創建索引的時候,會將索引拆分紅多個shard,每一個 shard 存儲部分數據。拆分多個 shard 是有好處的,一是支持橫向擴展,二是提升性能。這個 shard 的數據實際是有多個備份,就是說每一個 shard 都有一個 primary shard,負責寫入數據,可是還有幾個 replica shard。primary shard 寫入數據以後,會將數據同步到其餘幾個 replica shard 上去。
經過這個 replica 的方案,每一個 shard 的數據都有多個備份,若是某個機器宕機了,不要緊啊,還有別的數據副本在別的機器上呢。
es 集羣多個節點,會自動選舉一個節點爲 master 節點,這個 master 節點其實就是幹一些管理的工做的,好比維護索引元數據、負責切換 primary shard 和 replica shard 身份等。要是 master 節點宕機了,那麼會從新選舉一個節點爲 master 節點。
若是是非 master節點宕機了,那麼會由 master 節點,讓那個宕機節點上的 primary shard 的身份轉移到其餘機器上的 replica shard。接着你要是修復了那個宕機機器,重啓了以後,master 節點會控制將缺失的 replica shard 分配過去,同步後續修改的數據之類的,讓集羣恢復正常。
說得更簡單一點,就是說若是某個非 master 節點宕機了。那麼此節點上的 primary shard 不就沒了。那好,master 會讓 primary shard 對應的 replica shard(在其餘機器上)切換爲 primary shard。若是宕機的機器修復了,修復後的節點也再也不是 primary shard,而是 replica shard。
es讀取數據的過程
查詢,GET某一條數據,寫入了某個document,這個document會自動給你分配一個全局惟一的id,doc id,同時也是根據doc id進行hash路由到對應的primary shard上面去。也能夠手動指定doc id,好比用訂單id,用戶id。
1)客戶端發送請求到任意一個node,成爲coordinate node
2)coordinate node對document進行路由,將請求轉發到對應的node,此時會使用round-robin隨機輪詢算法,在primary shard以及其全部replica中隨機選擇一個,讓讀請求負載均衡
3)接收請求的node返回document給coordinate node
4)coordinate node返回document給客戶端
查詢的時候根據某一id查詢doc,這時候就是找一個協調節點,協調節點根據id路由找到shard而後返回數據