elasticsearch搜尋-最基本的工具
阿新 • • 發佈:2022-04-13
搜尋-最基本的工具
- 現在我們已經學會了如何使用es作為一個Nosql風格的分散式檔案儲存系統,
es的真正強大之處在於可以從無規律的資料中找出有意義的資訊,從大資料到大資訊 - es不只會儲存文件,為了能被搜尋到也會為文件新增索引,這也是為什麼我們使用結構化的json文件
而不是無結構的二進位制資料 - 文件中的每個欄位都將被索引,並且可以被查詢,不僅如此,在簡單查詢時,es可以使用所有(all)這些索引欄位
以驚人的速度返回結果,這是你永遠不會考慮用傳統資料庫去做的一些事情 - 搜尋可以做到
- 在類似於gender或者age這樣的欄位上使用結構化查詢,或者join_date這樣的欄位上使用排序, 就像sql的結構化查詢一樣
- 全文檢索,找出所有匹配關鍵字的文件並按照相關性(relevance)降序排序後返回結構
- 以上二者兼而有之
- 很多搜尋都是開箱即用的,為了充分挖掘es的潛力,需要理解下面三個概念
(1) 對映(mapping),描述資料在每個欄位中是如何儲存的
(2) 分析(analysis),全文是如何處理可以被搜尋到的
(3) 領域特定查詢語言(Query DSL),es中強大靈活的查詢語言
空搜尋
- 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不是停止查詢,
多索引、多型別
- 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個的原因, 也不要進行深度的分頁
輕量搜尋
-
有兩種形式的搜尋API,一種是輕量的查詢字串版本,要求在查詢字串中傳遞所有引數
另一種是完整的請求體版本,要求使用json格式和更豐富的查詢表示式作為搜尋語言 -
查詢字串非常適合於命令列做即席查詢,
GET/_search?q=tweet:use
下一個查詢在 name 欄位中包含 john 並且在 tweet 欄位中包含 mary 的文件
實際上查詢時這樣的:+name:john +tweet:mary
, 但是查詢字串引數所需要的 百分比編碼 (譯者注:URL編碼)實際上更加難懂:
GET/_search?q=%2Bname%3Ajohn+%2Btweet%3Amary
-
_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欄位不在有用的時候,可以將它設定為失效,
- 更復雜的查詢
- 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,查了能完成上述所有功能,還有其它功能