本篇主要介紹搜索的報文結構含義、搜索超時時間的處理過程,說起了一下多索引搜索和輕量搜索,最後將精確搜索與全文搜索作了簡單的對比。前端
搜索API最簡單的形式是不指定索引和類型的空搜索,它將返回集羣下全部索引的全部文檔(默認顯示10條):java
GET /_search
node
響應的結果示例(有篩選,只取了一條document做爲示例):segmentfault
{ "took": 2, "timed_out": false, "_shards": { "total": 5, "successful": 5, "skipped": 0, "failed": 0 }, "hits": { "total": 3, "max_score": 1, "hits": [ { "_index": "music", "_type": "children", "_id": "2", "_score": 1, "_source": { "name": "wake me, shark me", "content": "don't let me sleep too late, gonna get up brightly early in the morning", "language": "english", "length": "55", "likes": 9 } } ] } }
針對響應報文的字段,咱們作一些簡單解釋:數組
默認不使用timeout參數,若是某些場景下,低響應比搜索完整結果更重要,能夠指定timeout爲10ms或1s,在指定的超時時間內,Elasticsearch會把已經成功搜索到的文檔返回。
注意timeout不是中止執行查詢,它只是告訴Coordinate Node返回到指定時間爲止收集到的結果,而且關閉鏈接,在ES後臺,其餘node正在進行的查詢並不會中斷,只是結果沒人要了。網絡
舉個例子:某電商平臺商品SKU品類300萬條,輸入某個關鍵字查詢,有2000條記錄匹配,可是要查15秒鐘,一個搜索要等15秒纔出結果,顯得太不專業了,產品有SLA要求,必須1秒內出結果,最快的解決方案是查詢使用參數timeout=1s,前端分頁顯示默認只展現20條,1秒內的查詢結果要填滿這20條仍是比較容易的。架構
一個搜索請求,能夠同時寫多個索引名稱,這叫作multi-index搜索模式。併發
/_search:全部索引,全部type下的全部數據都搜索出來
/index1,index2/_search:同時搜索兩個index下的數據
/1,2/_search:按照通配符去匹配多個索引分佈式
單一索引下搜索時,ES會轉發請求到索引的每一個分片中,shard或replica都可,而後收集結果返回。多索引時,原理相同,只是涉及的分片更多。另外搜索一個索引有5個分片和搜索5個索引各有一個分片,性能是等價的。高併發
順帶咱們看一下搜索原理示意圖:
有兩種形式的搜索API,一種是query string search,查詢條件和排序規則寫在request URI裏,也叫輕量搜索;另外一種是query DSL,查詢條件等信息用JSON格式寫在request body裏。
輕量搜索的示例:
單個字段搜索,"q="後面接的是查詢條件"field:text",field是字段名,text是搜索的關鍵詞,有三種前綴修飾符:
GET /music/children/_search?q=content:friend GET /music/children/_search?q=+content:friend GET /music/children/_search?q=-content:friend
匹配的條件越多,文檔就越相關。
若是多個字段搜索,多個條件之間要有空格:
GET /music/children/_search?q=-content:friend +name:wake
若是"q="後面沒寫field,直接跟的是搜索關鍵詞,表示搜索指定索引下的全部字段,以下:
GET /music/children/_search?q=friend
只要music索引下的document,任何一個字段包含friend,就能搜索出來。那_all是怎麼來的?
_all是Elasticsearch中的元數據,在創建索引的時候,新增一個document裏面包含了多個field,此時,es會自動將多個field的值,所有用字符串的方式串聯起來,變成一個長的字符串,做爲_all field的值,同時創建索引。後面若是在搜索的時候,沒有對某個field指定搜索,就默認搜索_all field。
找個document示例:
"name": "wake me, shark me", "content": "don't let me sleep too late, gonna get up brightly early in the morning", "language": "english", "length": "55", "likes": 9
"wake me, shark me don't let me sleep too late, gonna get up brightly early in the morning english 55 9",做爲這一條document的_all field的值,同時進行分詞後創建對應的倒排索引
輕量搜索在開發階段會拿這些命令來作一些簡單的查詢,實際生產中用得比較少,語法複雜容易錯,而且可閱讀性低,遇到重量級查詢,還有可能會把ES集羣拖垮。
Elasticsearch的數據類型能夠分紅兩類:精確值和全文。
精確值如日期、ID,數值類型,有些文本類型也能夠表示精確值,如郵箱、經常使用縮寫等等。精確值的一個特色是必須徹底相同、大小寫敏感,很容易查詢,hello與Hello是不相等的,日期爲2019-11-20的字段值,輸入2019是搜索不到的。
全文數據就微妙得多,拿英文來講,各類詞根變化、大小寫轉換、同義詞、縮寫,漢字方面各類分詞、詞庫、網絡詞等,都但願匹配程度能高一些,可以理解咱們的意圖,舉幾個中文例子:
全文搜索方面,最基本的步驟是先分詞,再索引,而後搜索時進行匹配,英文相對好辦,中文方面有相像不到的難點要去克服。
本篇介紹搜索的基礎知識,闡述搜索結果的含義,多索引搜索和輕量搜索的基本使用,最後對比了一下精確搜索與全文搜索,以及著名的中文分詞大坑,謝謝。
專一Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公衆號:Java架構社區