1. 程式人生 > 其它 >elasticsearch搜尋-最基本的工具

elasticsearch搜尋-最基本的工具

搜尋-最基本的工具

  1. 現在我們已經學會了如何使用es作為一個Nosql風格的分散式檔案儲存系統,
    es的真正強大之處在於可以從無規律的資料中找出有意義的資訊,從大資料到大資訊
  2. es不只會儲存文件,為了能被搜尋到也會為文件新增索引,這也是為什麼我們使用結構化的json文件
    而不是無結構的二進位制資料
  3. 文件中的每個欄位都將被索引,並且可以被查詢,不僅如此,在簡單查詢時,es可以使用所有(all)這些索引欄位
    以驚人的速度返回結果,這是你永遠不會考慮用傳統資料庫去做的一些事情
  4. 搜尋可以做到
  • 在類似於gender或者age這樣的欄位上使用結構化查詢,或者join_date這樣的欄位上使用排序, 就像sql的結構化查詢一樣
  • 全文檢索,找出所有匹配關鍵字的文件並按照相關性(relevance)降序排序後返回結構
  • 以上二者兼而有之
  • 很多搜尋都是開箱即用的,為了充分挖掘es的潛力,需要理解下面三個概念
    (1) 對映(mapping),描述資料在每個欄位中是如何儲存的
    (2) 分析(analysis),全文是如何處理可以被搜尋到的
    (3) 領域特定查詢語言(Query DSL),es中強大靈活的查詢語言

空搜尋

  1. GET /_search
  • 返回結果中最重要的就是hits,它包含total欄位來表示匹配到的文件總數,
    並且一個hits陣列包含所查詢結果的前10個文件,
    在hits陣列中,每個文件包含_index、_id、_score相關性、_source原json文件,
    這意味著我們可以直接從返回的搜尋結果中使用整個文件,這不像其它搜尋引擎,僅僅返回文件的id
    需要你單獨去獲取文件
    每個文件都有一個_score,它衡量了文件與查詢的匹配程度,預設情況下,首先返回最相關的文件結果,
    也就是說,返回的文件,是按照_score降序排序的,在這個例子中,我們沒有指定任何查詢,
    因此所有的文件具有相同的相關性,因此對所有的結果而言1是中性的_score
  • max_score是與查詢文件的_score的最大值
  • took值告訴我們執行整個搜尋請求耗費了多少毫秒
  • _shards告訴我們查詢中參與分片的總數,以及這些分片成功了多少個失敗了多少個,
    加入災難級故障我們丟失了一個分片和他對應的副本,那麼該分片的查詢將不能做出響應,
    這樣的話,es會報告這個分片是失敗的,但是還會繼續返回剩餘分片的結果
  • time_out值告訴我們查詢是否超時,預設情況下,搜尋請求不會超時
    如果低響應時間比完成結果更重要,你可以指定timeout為10或者10ms, 或者1s
    GET /_search?timeout=1ms
    在請求超時之前,es將會返回已經成功從每個分片獲取的結果
    應當注意的是timeout不是停止查詢,

多索引、多型別

  1. es轉發每一個搜尋請求到主分片或者副本分片,彙集搜尋出來的前10個結果返回給我們
    當我們想在一個索引或者多個索引下搜尋文件時,就可以在url中指定對應的索引
GET /gb/_search
GET /gb,us/_search
GET /g*,*s/_search

當在單一的索引下進行搜尋的時候,es轉發搜尋請求到索引的每個分片中,可以是主分片也可以是副本分片
然後從每個分片中收集結果,多索引搜尋也是相同的工作方式,只不過是搜尋分片會更多一些。
搜尋一個索引有5個主分片和搜尋5個索引各有一個分片準確來說是等價的

分頁

GET /_search?size=5  第一頁5條
GET /_search?size=5&from=5  第二頁5條
GET /_search?size=5&from=10  第三頁5條

考慮到分頁深度以及一次請求太多結果的情況,結果集在返回之前先進行排序,但請記住一個請求經常跨越多個分片,
每個分片都產生自己的排序結果,這些結果需要進行集中排序以保證整體順序是正確的

在分散式系統中深度分頁
理解為什麼深度分頁是有問題的,假設在一個有5個主分片的索引中進行搜尋,當我們請求結果的第一頁(1-10),
每個分片產生前10的結果,並返回給協調節點,協調節點對50個結果進行排序得到全部結果的前10個

現在假設我們請求第1000也(10001-10010),5個主分片都需要獲取前10010個結果,然後傳送給協調節點
協調節點需要對50050個結果進行排序獲取前10個結果,然後丟掉剩餘的50040個

可以看到在分散式系統中,對結果排序的成本隨分頁的深度成指數上升,
這就是web搜素引擎對任何查詢都不要返回超過1000個的原因, 也不要進行深度的分頁

輕量搜尋

  1. 有兩種形式的搜尋API,一種是輕量的查詢字串版本,要求在查詢字串中傳遞所有引數
    另一種是完整的請求體版本,要求使用json格式和更豐富的查詢表示式作為搜尋語言

  2. 查詢字串非常適合於命令列做即席查詢,
    GET /_search?q=tweet:use
    下一個查詢在 name 欄位中包含 john 並且在 tweet 欄位中包含 mary 的文件
    實際上查詢時這樣的:+name:john +tweet:mary, 但是查詢字串引數所需要的 百分比編碼 (譯者注:URL編碼)實際上更加難懂:
    GET /_search?q=%2Bname%3Ajohn+%2Btweet%3Amary

  3. _all欄位
    這個簡單的搜尋返回包含mary的所有文件
    GET /_search?q=mary
    es是如何在不同的欄位中查詢到結果的呢,當索引一個文件的時候,es取出所有欄位的值拼接成一個大字串
    作為_all欄位進行索引,例如當索引這個文件是:

{
    "tweet":    "However did I manage before Elasticsearch?",
    "date":     "2014-09-14",
    "name":     "Mary Jones",
    "user_id":  1
}

這就好似增加了一個名叫_all的額外欄位,
"However did I manage before Elasticsearch? 2014-09-14 Mary Jones 1"
除非設定特定欄位,否則查詢字串就使用_all欄位進行搜尋

在剛開始開發一個應用時,_all欄位是一個很實用的特性,之後你會發現用指定欄位來代替_all欄位,
將會更好控制搜尋結果,當_all欄位不在有用的時候,可以將它設定為失效,
  1. 更復雜的查詢
  • name 欄位中包含 mary 或者 john
  • date 值大於 2014-09-10
  • _all 欄位包含 aggregations 或者 geo
    +name:(mary john) +date:>2014-09-10 +(aggregations geo)
    查詢字串做了適當的編碼後,可讀性很差
    GET /_search?q=%2Bname%3A(mary+john)+%2Bdate%3A%3E2014-09-10+%2B(aggregations+geo)
    所以在生產環境中還是建議使用request body查詢API,查了能完成上述所有功能,還有其它功能

參考文件