基本概念:html
索引Indexjava
es吧數據放到一個或者多個索引中,若是用關係型數據庫模型對比,索引的地位與數據庫實例(db)至關。索引存放和讀取的基本單元是文檔 (document)。es內部使用的是apache lucene實現的索引中數據的讀寫。(es被視爲單獨的一個索引,在lucene中不止一個,由於分佈式中,es會用到分區shards和備份 replicas機制講一個索引存儲多份)。算法
文檔document數據庫
在es中,文檔主要是存儲實體。全部的es應用需求最後都須要統一建成一個檢索模型:檢索相關文檔。apache
文檔由一個或多個域,每一個域field由一個域名或多個值組成(有多個值的稱爲多值域)。json
在es中每一個文檔均可能會有不一樣的域field集合;也就是說文檔是沒有固定的模式和贊成的結構的。文檔之間保持的類似性便可。api
在客戶端角度來看,文檔就是一個json對象。緩存
參數映射 全部的文檔在存儲以前都必須分析(analyze)流程,用戶能夠配置輸入文本分解成token的方式:哪些token唄濾掉;或者其它的處理流程,好比去除html標籤。服務器
文檔類型(type)併發
每一個文檔在es中都必須設定它的類型。文檔類型使得同一個索引中在存儲結構不一樣文檔時,只需根據文檔類型就能夠找到對應的參數映射信息,方便文檔的存取。
節點Node
單獨es服務器實例成爲一個節點。
集羣Cluster
集羣可以存儲超出單機容量的信息。因爲目前單點就能夠知足我們的需求,就不詳細介紹了。
索引副本Replica
經過索引分片機制能夠想es集羣中導入超過單機容量的數據,客戶端操做任意一個節點接口實現對集羣數據的讀寫。(不作詳細解釋了)
時間之門gateway
在運行的過程當中,es會收到集羣的狀態,索引的參數等信息。這些唄存儲在gateway中。
es背後核心理念:
es是構造極少數的幾個極少數的概念之上的。
開箱急用。
天生集羣。
自動容錯。
擴展性強。
es工做原理:
啓動過程:
當es節點啓動後,會利用 多播(multicast)或單播(別問我什麼是單播,多播,不必糾結這些)尋找病簡歷連接。如圖:
在集羣中,一個節點唄選舉成主節點。這個節點扶着管理集羣的狀態,當集羣的拓展結構改變時把索引分區分派到相對性的節點上。
在用戶角度看節點在es中並無佔據主要位置,這與其它系統是不一樣的(數據庫系統)。實際上用戶並不須要知道哪一個節點是主節點;全部的操做需求 能夠發到任意節點,es內部完成這些工做。必要時任意節點均可以併發的把查詢自居分發到其餘節點,而後合併各個節點返回的查詢結果。最後返回用戶一個完整 結果集。全部的這些工做不須要通過主節點轉發(節點以前經過p2p的方式通信)。
在必要時,會進行恢復工做。這時主節點會去檢查哪些分片可用,決定用哪些分片。處理完後,集羣轉入黃色狀態。
這意味着集羣能夠處理搜索請求了。可是尚未火力全開(這主要是因爲全部的主索引分區都已經分配好了,可是索引副本尚未)。接下來就是找到復 制好的分區,病設置成索引副本。當一個分區數量太少時,主節點會界定將缺乏的分區放到哪一個節點中,而且依照主分區建立副本。全部工做完成後,集羣就會變成 綠色狀態(標示全部的主分區的索引副本都已經分配完成了)。
探測是吧節點
在正常工做時,主節點會監控全部節點,查看各個節點是否工做正常。若是在指定的時間裏,節點沒法訪問,就唄視爲出現故障了,接下來錯誤處理程序 就會啓動。集羣須要均衡——因爲該節點出現故障,分配到該節點的索引分片丟失。其實節點上相應的分區就會吧工做接管過來的這個過程能夠經過配置知足用戶需 求。
因爲只是展現es的工做原理,就如下圖三個節點的集羣爲例。集羣中有一個主節點和兩個數據節點。主節點想其餘節點發送ping命令後等待迴應。若是獲得迴應(實際上可能得不到恢復ping命令個數,取決於用戶配置),改節點就會被移出集羣。
與es進行通信
歸根到底,最重要的是如何往es中添加數據以及如何查詢數據。es提供了api,這些api都是基於rest風格。並且這些api很是容易與其餘可以處理http的系統進行集羣。
es爲數據應該伴隨在url中,或做爲請求主體requst body。以一種json格式的文檔發送給服務器。
es內部,節點之間通信解釋用的先關javaapi。
重點來咯
索引數據
es提供了4中索引數據的方法。最簡單的就是索引api。經過它能夠將文檔添加到指定的索引中去。好比curl工具。我能夠經過以下命令建立一個新的文檔
第二、3中方法,能夠經過bulk API和UDP API批量添加文檔。一般的bulk API採用HTTP協議,UDP bulk api採用非鏈接的數據包協議。UDP協議傳輸速度更快,但可靠性差點、最後一種是經過rivier插件。river運行在es集羣的節點上,可以從外部 系統中獲取數據。
有一點須要注意,索引數據的曹組只會發生在主分區上,而不會發生在分區副本上。若是索引數據的請求發送到節點上沒有合適的分片或者分片副本,那麼請求就會被轉發到含有主分區的節點。
數據查詢
查詢api在es中有着很大的比重。經過query DSL(基於json,用於構造複雜的語言)
使用類型查詢:簡單關鍵詞、短語、區間、布爾、模糊、跨度、通配符、地理位置等查詢方式。
經過組合簡單查詢構造複雜的查詢。
過濾文檔,去除不符合標準的文檔並且不影響打分排序。
查找給定文檔的類似文檔。
查找給定短語的搜索建議和查詢短語修正。
經過faceting構建動態的導航和數據統計。
使用prospective search並且找到匹配寫定文檔的查詢語句(prospective search一種推送方式。用戶的查詢語句存儲在索引中,若是新的文檔添加到索引中,就把文檔關聯到匹配的查詢語句中。這種適合於新聞,博客等定時更新的場景)。
關於數據查詢,其核心在於查詢過程不是一個簡單、單一的流程。經過這個過程分爲兩個階段:查詢階段和結果彙總階段。在查詢分發階段,會從各個分支中查詢數據;在結果彙總階段,會從各個分羣上查詢到結果進行合併,排序等其餘處理過程,而後返回給用戶。
用戶能夠經過指定搜索類型來控制查詢的分發和彙總過程。
索引參數設置
es索引參數會自動配置
文檔結構以及域類型會自動識別。固然es也容許用戶自定修改默認配置。
好比,自行配置不少參數,好比經過mapping配置索引中的文檔結構,設置分區shard和副本replica的個數,設置文本組件……
集羣管理和監控
經過管理和監控部分的api,用戶能夠更改集羣設置。好比調整節點發現機制或更改索引的分片策略。用戶能夠查看集羣狀態信息,或者每一個節點和索引和統計信息。集羣監控的api很是普遍。
強大的用戶查詢語言DSL
if/idf打分公式
這個就是打分公式的真面目。若是隻是爲了調整查詢語句之間的關聯關係,用戶沒必要去理解它的原理。但只搜啊要知道它是如何工做的。
lucene概念上的打分公式
上面展現了布爾信息檢索和向量空間信息檢索模型的組合。(這個暫時忽略)
能夠了解更多東西能夠去這裏
從es的角度看打分排序
最重要的是利用lucene構建起來的es容許用戶修改默認的打分算法。但es不只僅是lucene的簡單封裝,由於es中,文檔排序並不是徹底 依賴apache lucene的打分算法。es實現了多種不一樣的查詢類型,這些查詢類型能夠徹底依賴與文檔的打分計算方式,es容許經過腳本定製文檔的打分方式。
查詢重寫機制
若是你曾經使用過不少不一樣的查詢類型,好比前綴查詢和通配符查詢,從本質上,任何的查詢均可以視爲對多個關鍵詞查詢。查詢重寫(query rewrite),es對用戶查詢進行了重寫,這樣作爲了保證性能。重寫過程是吧lucene角度認爲原始的、開銷大的查詢對象轉變成一系列開銷小的查詢 對象的一個過程。
前綴查詢:
例如:
我是知道全部字符以j開頭的文檔。這個需求很是簡單,在client索引上運行
查詢結果的重打分
有些場景對查詢語句的結果文檔進行從新打分是頗有必要的。從新打分的緣由可能各有相同。
其中一個緣由多是處於性能考慮,好比對整個有序的結果集進行重排序開銷會很大,一般就會只對結果集進行重排序。
理解重打分
在es中,重打分是一個對限定數目的查詢結果進行再次打分的一個過程。這意味着es會根據新的打分規則對結果的前n個文檔從新進行一次排序
例
rescore query的結構:
重打分的參數
在查詢語句的rescore對象中,用戶能夠添加以下參數
window_size提供了與N個文檔的相關信息。用於執行分片上用於重打分的文檔個數
query_weight默認1;原查詢的打分會先乘以query_weight,而後與rescore的得分相加。
rescore_query_weight默認1,rescore的打分會先乘該值,在與原查詢的得分相加。
rescore_mode默認tatal;在es0.90.0中引入用來指定重打分文檔的打分方式。可選值:total,max,avg和multiply。
total:最終得分爲原查詢得分和rescore得分的和;
max,最終得分爲原查詢得分和rescore得分的最大值;
min,最終得分爲原查詢得分和rescore得分的最小值;
avg,最終得分爲原查詢得分和rescore得分的平均值;
multiply,兩種查詢的得分相乘。
例如設置recore_mode參數值爲total,文檔最終得分是
查詢結果的排序
當給es發送查詢命令時,返回的文檔集合默認會按照計算出來的文檔打分排序。這個一般是
用戶但願的:結果集中的第一個文檔就是查詢命令想要的文檔。然而,有事咱們但願改變這種排序
。
update API
當往索引中添加新的文檔到索引中時,底層的lucene工具包會分析每一個域,生成token流
token流過濾後獲得倒排索引。在這個過程當中輸入文版中一系誒沒必要要的信息會丟掉。
這些沒必要要的信息多是一些特殊詞的位置,一些停用的詞或用同義詞代替的詞,或者詞尾
。這也是爲何沒法對lucene中的文檔進行修改,每次修改一個文檔時,必須吧文檔全部域 添加到索引中。es經過_source這個代理域來存儲或檢索文檔中的真是數據。
當咱們想更新文檔時,es會把數據放到_souce域中,而後作出修改,最後吧更新後的文檔
添加到索引中。讓然前提是_source域的這項特性必須生效。文檔更新命令只能更新一個文檔
查詢命令的文檔更新尚未出來。
更新:
使用update API建立或刪除文檔
update API不只能夠修改某個域,同時也能操做整個文檔。
upsert特性使得在定位到一個不存在的文檔是,它會被建立愛你出來:
若是文檔存在,該命令將重置year域中的值;不然會被建立。新的文檔包含upset中定義的titile域。固然,上面的命令還有可使用腳本:
update還容許用戶選擇性的刪除整個文檔。
filters優化查詢:
es支持多種類型的查詢,可是查詢那個匹配成功,哪一個應該呈現給用戶,查詢並非惟一的。es查詢dsl容許用戶使用絕大數查詢都會有各自的標示。
過濾器(filters)和緩存
ES提供了特殊的緩存,filter cache來存儲filters獲得的結果集。此外,存儲filters不須要太多的內存(它只保留一種信息,即哪些文檔與filter相匹配),同時它能夠與其餘查詢複用,極大的提升查詢的性能。
例:
該命令查詢獲得知足以下條件的文檔:name域值爲joe同時值爲1981。
用上面命令格式構建查詢,查詢對象會將全部的條件綁定到一塊兒存儲到緩存中;所以若是咱們查詢人名相同但出生年份不一樣的運動員,es沒法重用上面查詢命令中的任何信息。
所以,咱們須要優化下查詢。因爲1千我的可能有一千我的名,因此人名不太適合緩存起來;可是年份比較適合。所以咱們引入一個不一樣的查詢命令,將一個簡單的query與一個filter結合起來。
咱們使用一個filtered類型的查詢對象,查詢對象將query元素與filter元素包含進去。第一次運行查詢命令後,es會吧filter緩存起來,若是有查詢用到同樣的filter,就會直接用緩存。
並不是全部的filters都會被默認緩存起來
實際上es不會緩存全部的filters。這是由於部分filters會用到域數據緩存(field date cache)。該緩存通常用於按域值排序和faceting操做場景中。默認狀況,以下filters不會唄緩存:
儘管最後三種不會用到域緩存,它們主要用於控制filters,所以不會被緩存,可是它們控制的filters在用時都已經緩存好了。
更改es緩存行爲
es容許用戶經過_cache和_cache_key屬性自行開啓或關閉filters功能。
假設咱們將關鍵詞過濾器結果緩存起來,病給緩存項的key取名爲year_1981_cache:
也能夠用下面命令關閉過濾器緩存:
爲了獲取更多的控制權,咱們須要給緩存項的key取名。
好比,有些查詢複用機很少,咱們但願指定定時清理這些查詢的緩存。若是不指定_cache_key。就只能清除整個過濾器緩存filter cacahe;反之,只需執行以下命令:
關鍵詞查找過濾器
緩存和標準的查詢並非所有內容。
索引定義了id信息,名字,用戶購書的id列表。
一些測試數據:
假設咱們但願展現某個用戶購買的全部數據,以id爲1的user爲例。
term filter的工做原理
一個普通的es查詢命令。它只是一個過濾查詢,包含一個全量查詢和一個terms過濾器。
只是查詢命令中,terms過濾器使用了一種不一樣的技巧——不明確指定某些term值,而是從索引中動態加載。
過濾器基於id域,由於咱們只須要id域就整合其它全部的屬性。
index屬性指明瞭加載terms的索引源。
type屬性告訴es咱們的目標文檔類型。
id屬性指明咱們在執行索引文檔的books域。
path屬性告訴es應該從哪一個域中加載term。
terms lookup filter的緩存設置
filters和scope在es faceting的應用
faceting的結果只基於查詢結果。如使用filters,那filters不會對facet用來的統計計算文檔產生影響。
scope,能夠擴展facet統計計算的文檔範圍。