Elasticsearch系列---初識搜索

概要

本篇主要介紹搜索的報文結構含義、搜索超時時間的處理過程,說起了一下多索引搜索和輕量搜索,最後將精確搜索與全文搜索作了簡單的對比。前端

空搜索

搜索API最簡單的形式是不指定索引和類型的空搜索,它將返回集羣下全部索引的全部文檔(默認顯示10條):java

GET /_searchnode

響應的結果示例(有篩選,只取了一條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
        }
      }
    ]
  }
}

針對響應報文的字段,咱們作一些簡單解釋:數組

  • took:整個搜索請求花費了多少毫秒。
  • time_out:查詢是否超時。
  • _shards:查詢中參與分片的總數,其中成功的分片數量,失敗的分片數量,以及跳過的分片數量。正常狀況下不會有失敗的分片數量,若是發生了災難級別的故障,超過了容錯的最大node數量,可能會同時丟失shard和replica,此時會報告這些分片是失敗的,但仍是會繼續返回剩餘可用分片的查詢結果。
  • hits:包含total表示匹配到的文檔總數,max_score值是全部匹配文檔中_score的最大值。
  • hits.hits:數組內包含匹配的文檔的完整信息,默認查詢前10條數據,而且按_score降序排序。

timeout機制

默認不使用timeout參數,若是某些場景下,低響應比搜索完整結果更重要,能夠指定timeout爲10ms或1s,在指定的超時時間內,Elasticsearch會把已經成功搜索到的文檔返回。
注意timeout不是中止執行查詢,它只是告訴Coordinate Node返回到指定時間爲止收集到的結果,而且關閉鏈接,在ES後臺,其餘node正在進行的查詢並不會中斷,只是結果沒人要了。網絡

舉個例子:某電商平臺商品SKU品類300萬條,輸入某個關鍵字查詢,有2000條記錄匹配,可是要查15秒鐘,一個搜索要等15秒纔出結果,顯得太不專業了,產品有SLA要求,必須1秒內出結果,最快的解決方案是查詢使用參數timeout=1s,前端分頁顯示默認只展現20條,1秒內的查詢結果要填滿這20條仍是比較容易的。架構

設置timeout的查詢過程

多索引搜索

一個搜索請求,能夠同時寫多個索引名稱,這叫作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

_all元數據的原理

若是"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的數據類型能夠分紅兩類:精確值和全文。

  • 精確值(exact value)

精確值如日期、ID,數值類型,有些文本類型也能夠表示精確值,如郵箱、經常使用縮寫等等。精確值的一個特色是必須徹底相同、大小寫敏感,很容易查詢,hello與Hello是不相等的,日期爲2019-11-20的字段值,輸入2019是搜索不到的。

  • 全文(full text)

全文數據就微妙得多,拿英文來講,各類詞根變化、大小寫轉換、同義詞、縮寫,漢字方面各類分詞、詞庫、網絡詞等,都但願匹配程度能高一些,可以理解咱們的意圖,舉幾個中文例子:

  • 南京市長江大橋,有一些分詞器獲得的結果:南京/市長/江大橋,徹底不是咱們想的結果,咱們但願是:南京/南京市/長江/大橋/長江大橋。
  • 長春市長春街長春藥店,分詞分得不對,搞成這樣:長春/市長/春/街/長/春藥/店,結果就很尷尬了。

全文搜索方面,最基本的步驟是先分詞,再索引,而後搜索時進行匹配,英文相對好辦,中文方面有相像不到的難點要去克服。

小結

本篇介紹搜索的基礎知識,闡述搜索結果的含義,多索引搜索和輕量搜索的基本使用,最後對比了一下精確搜索與全文搜索,以及著名的中文分詞大坑,謝謝。

專一Java高併發、分佈式架構,更多技術乾貨分享與心得,請關注公衆號:Java架構社區
Java架構社區.jpg

相關文章
相關標籤/搜索