Elasticsearch入门教程(五):Elasticsearch查询(一)
_search
注意:_search即支持GET也支持POST
GET /_search // 空查詢:查詢所有索引下的所有文檔 GET /{index}/_search // 查詢某個索引下的前10條文檔 GET /{index}/{type}/_search // 查詢某個索引下某個類型的前10條文檔// 返回結果
took字段表示該操作的耗時(單位為毫秒),
timed_out字段表示是否超時,
_shards:在查詢中參與分片的總數,以及這些分片成功了多少個失敗了多少個
total:返回記錄數,本例是2條。
max_score:最高的匹配程度,本例是1.0。
hits:返回的記錄組成的數組。
返回的記錄中,每條記錄都有一個_score字段,表示匹配的程序,默認是按照這個字段降序排列。
查詢字符串
查詢字符串:就是在_search上使用GET參數的形式對search進行查詢過濾,即將參數追加到路徑上,此種方式有局限性,不夠靈活
- q: 通過加號+來指定查詢中的某個字段必須包含某個值,默認是加號,通過減號-來指定文檔中不能包含某個值,使用冒號將字段和值分隔,如 q=last_name:Smith,類似于關系型數據庫中的where中的 like和not like 操作,
- _source:用于指定要查詢的字段,默認會返回文檔中的所有字段,多個字段用逗號分隔
- size: 設置search是返回的消息的條數,默認是10
- from: 設置跳過的頁數,默認是0,可以通過from和size來達到分頁的目的
- sort: 指定對那個字段進行什么排序,默認是按照相關性評分來降續排序的_score, 例如sort=date:desc&sort=_score
- version: 版本號,用于更新和刪除操作,當文檔的版本等于指定的版本號時才能正常執行,否則會返回409 版本沖突 (樂觀并發控制)
- ersion_type=external 用于創建、修改、刪除操作 外部版本號:當使用外部版本號是es會檢查版本號是否比_version值小,如果小的話就正常執行,并將_version的值更改為外部的版本號, 例如version=5&version_type=external
- timeout=10ms 指定超時時間,默認單位是毫秒ms,也可以指定秒s,例如1s
- retry_on_conflict=n 參數來設置自動完成這項請求的次數,它的默認值是0,失敗前重新嘗試n次
- scroll=1m 游標查詢,保持游標查詢窗口一分鐘
查詢表達式DSL
使用查詢領域特定語言(Query Domain Specific Language) 簡稱為DSL, 需要使用JSON作為主體,請求體查詢
query
- match:模糊匹配,類似于SQL中的like,示例{ “match” : { “field” : “keyword” }},
- match_all:簡單的匹配所有文檔 {“match_all”: {}}
- match_phrase: 對于短語或者段落進行精確匹配
- match_phrase_prefix
- multi_match: 在多個字段上反復執行相同查詢
- bool 用于表示復合語句,用于組合多個查詢語句;將多查詢組合成單一查詢
- must 必須匹配這些條件才能被包含進來,表示并且的關系
- must_not 必須不 匹配這些條件才能被包含進來
- should 如果滿足這些語句中的任意語句,將增加 _score ,否則無任何影響。它們主要用于修正每個文檔的相關性得分。
- minimum_should_match:控制需要匹配的 should 語句的數量, 它既可以是一個絕對的數字,又可以是個百分比, 如 minimum_should_match: 2 或者 “minimum_should_match”: “75%”
- filter 必須匹配,但它以不評分、過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔, filter只是簡單的數據過濾,并不影響評分,因filter不計算評分,所以性能更好,請盡可能多的使用過濾式查詢
- exists 查找包含某個字段的文檔
- range 范圍,可以使用大于gt、大于等于gte、小于lt、小于等于lte作為查詢條件,可用于數字、日期類型、字符串
- term 精確查詢,對數值,日期,布爾,not_analyzed確切值字符串
- terms 指定多個匹配值,如果字段包含其中的任何一個,都會返回文檔,類似于SQL中的IN 操作
- constant_score: 恒定分數,它將一個不變的常量評分應用于所有匹配的文檔
- wildcard: 通配符, ? 匹配任意字符, * 匹配 0 或多個字符
- fuzzy: 模糊查詢
- dis_max:分離 最大化查詢(Disjunction Max Query)
- nested : 用于操作嵌套類型
highlight 高亮,匹配的結果會被 HTML字符包裹住,需要指定匹配的字段
- aggs 聚合操作,類似SQL中的Group By
- sort 排序
- from 偏移量,類似于SQL中limit中的offset
- size 返回數量,類似于SQL中limit中的count,可以通過from,size來達到分頁的效果
數據準備
DELETE /shop/goods/_all 刪除所有文檔
match 匹配查詢
全文檢索方式查詢,類似于關系型數據庫中的like操作,使用match時需要指定對那個字段進行全文檢索,以及對應的關鍵字, 關鍵字可以指定一個也可以指定多個,指定多個時表示或者的關系 類似于SQL中的or的功能。語法:
{ "match" : { "field" : "keyword" }} 類似于SQL中的where filed like ‘%keyword%’
{ "match" : { "field" : "keyword1 keyword2" }} 類似于SQL中的where field like ‘%keyword1%’ or field like ‘%keyword2%’
示例:
// 查詢name中包含“女裝”的文檔
GET /shop/goods/_search {"query": {"match": {"name": "女裝"}} }// 多詞查詢 :使用空格隔離多個單詞 // 查詢name中包含“外套” 或者or 包含 “休閑” 的文檔,多個關鍵字使用空格分隔,如果不指定operator默認是or GET /shop/goods/_search {"query": {"match": {"name": "外套 休閑"}} }// "name": "外套 休閑" or 等價于bool中的should GET /shop/goods/_search {"query": {"bool": {"should": ["match": { "name": "外套" },"match": { "name": "休閑" },]}} }// 查詢name中包含“外套” 并且 包含 “休閑” 的文檔,多個關鍵字使用空格分隔 GET /shop/goods/_search {"query": {"match": {"name": "外套 休閑","operator": "and"}} }// "name": "外套 休閑" and 等價于bool中的must GET /shop/goods/_search {"query": {"bool": {"must": ["match": { "name": "外套" },"match": { "name": "休閑" },]}} }// 多詞查詢中使用or只需要滿足一個即可,要求太低,使用and又必須所有詞項都必須滿足,要求又太高, // 使用minimum_should_match折中一下,最小匹配:可以指定一個百分比, // 例如指定4個詞項,一個是詞項是25就是至少要滿足2個詞項 GET /shop/goods/_search {"query": {"match": {"name": {"query": "春季 長袖 圓領 學生","minimum_should_match": "50%"}}} }// 效果和上面一樣,等價的 GET /shop/goods/_search {"query" : {"bool": {"filter": {"bool" : {"should" : [{ "term" : {"name" : "春季"}}, { "term" : {"name" : "長袖"}}, { "term" : {"name" : "圓領"}}, { "term" : {"name" : "學生"}}],"minimum_should_match": 2}}}} }// 查詢日期 GET /shop/goods/_search {"query": {"match": {"create_date": "2018-01-31"}} }match一般用于用引號括起來的值,如文本,日期,如果將match用于布爾或者數字等數據類型就變成精確匹配了,而不是全文檢索或者模糊匹配了
如果在一個精確值的字段上使用match,例如數字、日期、布爾或者一個 not_analyzed 字符串字段,那么它將會精確匹配給定的值:
match_all
簡單的匹配所有文檔
GET /shop/goods/_search {"query": {"match_all": {}} }// 上面簡寫成這樣,效果是一樣的 GET /shop/goods/_search {}// 同樣也可以去掉{},更加簡潔 GET /shop/goods/_searchmatch_phrase
對于短語或者段落進行精確匹配,
// match如果對一小段文本進行查詢,match首先對字段值進行分詞,然后對分詞進行匹配,相當于SQL中的name like '%女裝%' or name like '%冬季%' or name like '%外套%' GET /shop/goods/_search {"query": {"match": {"name": "女裝冬季外套"}} }GET /shop/goods/_search {"query": {"match_phrase": {"name": "女裝冬季外套"}} } // slop:讓相對詞序位置不那么嚴格 // 注意上面使用的是“女裝冬季外套”,而現在使用的是“套女裝冬季”, slop:允許每個詞放寬的間隔 // 盡管詞語的順序不正確,查詢仍然能匹配,因為我們為它設置了足夠高的slop值使匹配時的詞序有更大的靈活性。 GET /shop/goods/_search {"query": {"match_phrase": {"name": {"query": "外套女裝冬季","slop": 10}}} }match_phrase_prefix
match_phrase_prefix與match_phrase是一樣的,只是它允許在文本的最后一項中使用前綴匹配。
可以用于即時搜索(instant search) 或 輸入即搜索(search-as-you-type),例如,如果用戶輸入 johnnie walker bl ,我們希望在它們完成輸入搜索條件前就能得到:Johnnie Walker Black Label 和 Johnnie Walker Blue Label 。
GET /shop/goods/_search {"query": {"match_phrase_prefix": {"name": "女裝冬季外套"}} }// slop:讓相對詞序位置不那么嚴格 // 注意上面使用的是“女裝冬季外套”,而現在使用的是“套女裝冬季”, slop:允許每個詞放寬的間隔 // 盡管詞語的順序不正確,查詢仍然能匹配,因為我們為它設置了足夠高的slop值使匹配時的詞序有更大的靈活性。 GET /shop/goods/_search {"query": {"match_phrase_prefix": {"name": {"query": "外套女裝冬季","slop": 10}}} }prefix 查詢存在嚴重的資源消耗問題,短語查詢的這種方式也同樣如此。前綴 a 可能會匹配成千上萬的詞,這不僅會消耗很多系統資源,而且結果的用處也不大。
索引時輸入即搜索
## edge_ngram 自定義過濾器、分詞器 PUT /my_index {"settings": {"number_of_shards": 1, "analysis": {"filter": {"autocomplete_filter": { "type": "edge_ngram","min_gram": 1,"max_gram": 20}},"analyzer": {"autocomplete": {"type": "custom","tokenizer": "standard","filter": ["lowercase","autocomplete_filter" ]}}}} }## 測試分詞 GET /my_index/_analyze {"analyzer": "autocomplete","text": "quick brown" }PUT /my_index/_mapping/my_type {"my_type": {"properties": {"name": {"type": "text","analyzer": "autocomplete", ## 使用自定義的分詞器"search_analyzer": "standard" ## 配置查詢對應的分詞器}}} }POST /my_index/my_type/_bulk { "index": { "_id": 1 }} { "name": "Brown foxes" } { "index": { "_id": 2 }} { "name": "Yellow furballs" }## 搜索 GET /my_index/my_type/_search {"query": {"match": {"name": {"query": "brown fo"}}} }multi_match
多個字段上使用相同的值作為查詢條件
GET /shop/goods/_search {"query": {"multi_match": {"query": 268,"fields": ["price", "quantity"]}} }// 兩者效果相同 GET /shop/goods/_search {"query": {"bool": {"should": [{ "term": { "price": { "value": 268 } } },{ "term": { "quantity": { "value": 268 } } }]}} }// 查詢字段名稱的模糊匹配 // 字段名稱可以用模糊匹配的方式給出:任何與模糊模式正則匹配的字段都會被包括在搜索條件中, 例如可以使用以下方式同時匹配 book_title 、 chapter_title 和 section_title (書名、章名、節名)這三個字段:{"multi_match": {"query": "Quick brown fox","fields": "*_title"} }// 提升單個字段的權重 // 可以使用 ^ 字符語法為單個字段提升權重,在字段名稱的末尾添加 ^boost ,其中 boost 是一個浮點數: // chapter_title 這個字段的 boost 值為 2 ,而*_title 字段的默認 boost 值為 1 {"multi_match": {"query": "Quick brown fox","fields": [ "*_title", "chapter_title^2" ] (1)} }constant_score 常量分數
通常當查找一個精確值的時候,我們不希望對查詢進行評分計算。只希望對文檔進行包括或排除的計算,所以我們會使用 constant_score 查詢以非評分模式來執行 term 查詢并以一作為統一評分。
它將一個不變的常量評分應用于所有匹配的文檔。它被經常用于你只需要執行一個 filter 而沒有其它查詢(例如,評分查詢)的情況下。可以使用它來取代只有 filter 語句的 bool 查詢。在性能上是完全相同的,但對于提高查詢簡潔性和清晰度有很大幫助. 這種方式可以用來取代只有 filter 語句的 bool 查詢
GET /shop/goods/_search {"query": {"constant_score": {"filter": {"term": {"price": 268.00}}}} }查詢置于 filter 語句內不進行評分或相關度的計算,所以所有的結果都會返回一個默認評分 1
prefix 前綴查詢
前綴查詢:要查詢的字段必須沒有分詞
默認狀態下, prefix 查詢不做相關度評分計算,它只是將所有匹配的文檔返回,并為每條結果賦予評分值 1 。它的行為更像是過濾器而不是查詢。 prefix 查詢和 prefix 過濾器這兩者實際的區別就是過濾器是可以被緩存的,而查詢不行。
prefix 查詢或過濾對于一些特定的匹配是有效的,但使用方式還是應當注意。當字段中詞的集合很小時,可以放心使用,但是它的伸縮性并不好,會對我們的集群帶來很多壓力。可以使用較長的前綴來限制這種影響,減少需要訪問的量。
PUT /my_index {"mappings": {"address": {"properties": {"postcode": {"type": "keyword"}}}} }PUT /my_index/address/1 { "postcode": "W1V 3DG" }PUT /my_index/address/2 { "postcode": "W2F 8HW" }PUT /my_index/address/3 { "postcode": "W1F 7HW" }PUT /my_index/address/4 { "postcode": "WC1N 1LZ" }PUT /my_index/address/5 { "postcode": "SW5 0BE" }// prefix 查詢 GET /my_index/address/_search {"query": {"prefix": {"postcode": {"value": "W1"}}} }wildcard 和 regexp
與 prefix 前綴查詢的特性類似, wildcard 通配符查詢也是一種底層基于詞的查詢,與前綴查詢不同的是它允許指定匹配的正則式。它使用標準的 shell 通配符查詢: ? 匹配任意字符, * 匹配 0 或多個字符。
GET /my_index/address/_search {"query": {"wildcard": {"postcode": "W?F*HW" }} }// 詞必須以 W 開頭,緊跟 0 至 9 之間的任何一個數字,然后接一或多個其他字符 GET /my_index/address/_search {"query": {"regexp": {"postcode": "W[0-9].+" }} }wildcard 和 regexp 查詢的工作方式與 prefix 查詢完全一樣,它們也需要掃描倒排索引中的詞列表才能找到所有匹配的詞,然后依次獲取每個詞相關的文檔 ID ,與 prefix 查詢的唯一不同是:它們能支持更為復雜的匹配模式。
這也意味著需要同樣注意前綴查詢存在性能問題,對有很多唯一詞的字段執行這些查詢可能會消耗非常多的資源,所以要避免使用左通配這樣的模式匹配(如: *foo 或 .*foo 這樣的正則式)。
數據在索引時的預處理有助于提高前綴匹配的效率,而通配符和正則表達式查詢只能在查詢時完成,盡管這些查詢有其應用場景,但使用仍需謹慎。
prefix 、 wildcard 和 regexp 查詢是基于詞操作的,如果用它們來查詢 analyzed 字段,它們會檢查字段里面的每個詞,而不是將字段作為整體來處理。
range
用于查詢一個區間,一般用于日期和數值,支持 gt、gte、lt、lte, 示例{“range”: { “age”: { “gte”: 20, “lt”:30 }}} 類似于SQL中的 wher age >= 20 and age < 30
GET /shop/goods/_search {"query": {"range": {"price": {"gt": 200,"lte": 500}}} }// 日期類型 GET /shop/goods/_search {"query": {"range": {"create_date": {"gt" : "2014-01-01 00:00:00","lt" : "2014-01-07 00:00:00"}}} }// 日期計算:過去一小時 GET /shop/goods/_search {"query": {"range": {"create_date": {"gt" : "now-1h"}}} }// 日期計算:早于 2014 年 1 月 1 日加 1 月(2014 年 2 月 1 日 零時) GET /shop/goods/_search {"query": {"range": {"create_date": {"gt" : "2014-01-01 00:00:00","lt" : "2014-01-01 00:00:00||+1M"}}} }// 作用于字符串,性能相對較慢 "range" : {"title" : {"gte" : "a","lt" : "b"} }term
精確查詢:用于精確值匹配,對數值,日期,布爾,not_analyzed確切值字符串, term 查詢對于輸入的文本不 分析 ,所以它將給定的值進行精確查詢。
GET /shop/goods/_search {"query": {"term": {"is_discount": {"value": true}}} }terms
同term查詢,但是它允許指定多個匹配值,一般用于數組,如果字段包含其中的任何一個,都會返回文檔, 類似于where tag IN (‘value1’, ‘value2’, ‘value3’) 例如:{ “terms”: { “tag”: [ “search”, “full_text”, “nosql” ] }}
GET /shop/goods/_search {"query": {"terms": {"colors": ["白藍紅","綠色"]}} }exists
對于相同類型的文檔,可能有的文檔有某個字段,有的文檔沒有某個字段,查找包含或者不包含某個字段的文檔, 例如: {“exists”: { “field”: “title” }} ,exists 用于查找那些指定字段中是否有值 , 相當于SQL中的IS NOT NULL
null, [] (空數組)和 [null] 所有這些都是等價的,它們無法存于倒排索引中
這些查詢經常用于某個字段有值的情況和某個字段缺值的情況。
// 存在某個字段 GET /shop/goods/_search {"query": {"bool": {"filter": {"exists": {"field": "activity"}}}} }// 不存在某個字段 GET /shop/goods/_search {"query": {"bool": {"must_not": {"exists": {"field": "activity"}}}} }POST /my_index/posts/_bulk { "index": { "_id": "1" }} { "tags" : ["search"] } { "index": { "_id": "2" }} { "tags" : ["search", "open_source"] } { "index": { "_id": "3" }} { "other_field" : "some data" } { "index": { "_id": "4" }} { "tags" : null } { "index": { "_id": "5" }} { "tags" : ["search", null] }以上文檔集合中 tags 字段對應的倒排索引如下: Token DocIDs open_source 2 search 1,2,51. tags 字段有 1 個值。 2. tags 字段有 2 個值。 3. tags 字段缺失。 4. tags 字段被置為 null 。 5. tags 字段有 1 個值和 1 個 null 。// 1,2,5 滿足條件 GET /my_index/posts/_search {"query" : {"constant_score" : {"filter" : {"exists" : { "field" : "tags" }}}} }highlight:高亮
匹配的結果會被 HTML字符包裹住,需要指定匹配的字段,”highlight”: {“fields” : {“about” : {}}}
// 高亮: 匹配的結果會被 <em></em> HTML字符包裹住: curl -i -H 'Content-Type: application/json' -XGET 'http://localhost:9200/megacorp/employee/_search' -d ' {"query" : {"match_phrase" : {"about" : "rock climbing"}},"highlight": {"pre_tags" : ["<font color='red'>"],"post_tags" : ["</font>"],"fields" : {"about" : {}}} }'sort
排序,可以指定一個或者多個字段排序,多個字段使用數組包圍,例如:”sort”: { “date”: { “order”: “desc” }}
// 排序,默認情況下是按照相關性評分排序的,最相關的文檔排在最前, 默認按_score排序的 // 多級排序,使用date, _score排序 GET /_search { "query" : { "bool" : { "must": { "match": { "tweet": "manage text search" }}, "filter" : { "term" : { "user_id" : 2 }} } }, "sort": [ { "date": { "order": "desc" }}, { "_score": { "order": "desc" }},{ "ids" : { "order": "asc", "mode": "min"}} ] } mode:一般用于數組,可以使用min 、 max 、 avg 或是 sum,統計計算數組的指定值排序對字符串排序,sort對字符串排序需要使用到原始值raw,正常情況下文本可能會使用分詞器進行分詞,而分詞器會影響正常的排序,這時可以對同一個字段設置兩種類型,對文本設置成text類型,并設置分詞器,如果要搜索的話使用text類型字段,然后再為該字段設置一個原始值,該原始值raw字段的fields的數據類型設置為keyword,關鍵字數據類型是不分詞的,不分詞的字段可以作為字符串的排序
// fields 多字段:相當于對同一個字段值起不同的名字,賦予這個字段不同的屬性(如類型不同,分詞器不同等) PUT /school {"mappings": {"students": {"properties": {"name": {"type": "text","analyzer": "ik_max_word","fields": {"raw": {"type": "keyword"} }}}}} }// _score 和 max_score 字段都是 null 。計算 _score 的花銷巨大,通常僅用于排序; 我們并不根據相關性排序,所以記錄 _score 是沒有意義的。如果無論如何你都要計算 _score , 你可以將 track_scores 參數設置為 true GET /school/students/_search {"query": { "match": { "name": "abc" } }, "sort": [ { "name.raw": { "order": "desc" } } ] }// 強制計算評分 GET /school/students/_search {"track_scores": true,"query": { "match": { "name": "abc" } }, "sort": [ { "name.raw": { "order": "desc"} } ] }from
偏移量,類似于SQL中limit中的offset
size
返回數量,類似于SQL中limit中的count,可以通過from,size來達到分頁的效果
GET /shop/goods/_search {"from": 0,"size": 20 }游標查詢Scroll
使用from, size做分頁不能分頁太深,太深對性能營銷較大,一般獲取前1000條數據就算深了,游標查詢用于解決深度分頁帶來的性能問題。
scroll 查詢可以用來對Elasticsearch有效地執行大批量的文檔查詢,而又不用付出深度分頁那種代價。游標查詢允許我們 先做查詢初始化,然后再批量地拉取結果。 這有點兒像傳統數據庫中的 cursor 。游標查詢會取某個時間點的快照數據,查詢初始化之后索引上的任何變化會被它忽略。 它通過保存舊的數據文件來實現這個特性,結果就像保留初始化時的索引 ‘視圖’ 一樣。
深度分頁的代價根源是結果集全局排序,如果去掉全局排序的特性的話查詢結果的成本就會很低。 游標查詢用字段_doc來排序。 這個指令讓 Elasticsearch 僅僅從還有結果的分片返回下一批結果。啟用游標查詢可以通過在查詢的時候設置參數 scroll 的值為我們期望的游標查詢的過期時間,游標查詢的過期時間會在每次做查詢的時候刷新,所以這個時間只需要足夠處理當前批的結果就可以了,而不是處理查詢結果的所有文檔的所需時間。 這個過期時間的參數很重要,因為保持這個游標查詢窗口需要消耗資源,所以我們期望如果不再需要維護這種資源就該早點兒釋放掉。 設置這個超時能夠讓 Elasticsearch 在稍后空閑的時候自動釋放這部分資源。
// 保持游標查詢窗口一分鐘 // 關鍵字 _doc 是最有效的排序順序。 GET /shop/goods/_search?scroll=1m {"query": {"match_all": {}},"sort": ["_doc"],"size": 1000 }// 這個查詢的返回結果包括一個字段 _scroll_id, 它是一個base64編碼的長字符串 。 現在我們能傳遞字段 _scroll_id 到 _search/scroll {"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAMoFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAADKRZkNHJWQzRIOFFmLWEwc1U4NEFkRXZnAAAAAAAAAyoWZDRyVkM0SDhRZi1hMHNVODRBZEV2ZwAAAAAAAAMrFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAADLBZkNHJWQzRIOFFmLWEwc1U4NEFkRXZn","took": 1,"timed_out": false,... }// 查詢接口獲取下一批結果: GET /_search/scroll {"scroll": "1m","scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAKbFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAACnBZkNHJWQzRIOFFmLWEwc1U4NEFkRXZnAAAAAAAAAp0WZDRyVkM0SDhRZi1hMHNVODRBZEV2ZwAAAAAAAAKeFmQ0clZDNEg4UWYtYTBzVTg0QWRFdmcAAAAAAAACnxZkNHJWQzRIOFFmLWEwc1U4NEFkRXZn" }這個游標查詢返回的下一批結果。 盡管我們指定字段 size 的值為1000,我們有可能取到超過這個值數量的文檔。 當查詢的時候, 字段 size 作用于單個分片,所以每個批次實際返回的文檔數量最大為 size * number_of_primary_shards.
注意游標查詢每次返回一個新字段 _scroll_id。每次我們做下一次游標查詢, 我們必須把前一次查詢返回的字段 _scroll_id 傳遞進去。 當沒有更多的結果返回的時候,我們就處理完所有匹配的文檔了。
bool
布爾查詢,這是一個很重要的查詢,它可以將其它多種查詢封裝成一個大的查詢,可以使用邏輯操作符(類似于sql中的and、not、or)來組裝各個條件, 這是個復合過濾器(compound filter) ,它可以接受多個其他過濾器作為參數,并將這些過濾器結合成各式各樣的布爾(邏輯)組合
用于表示復合語句,用于組合多個查詢語句;將多查詢組合成單一查詢,bool可以放到query下面,也可以嵌套在某個子條件(must、should、must_not)里, 通過嵌套可以構造出更加復雜的過濾條件。
- must: 必須匹配這些條件才能被包含進來。 表示并且的關系,與 SQL中的AND 等價,例如{"must": [{"match": {"desc": "xxx"}}, {"term": { "quantity": 999}}]},類似于SQL中的where desc like '%xxx%' and quantity = 999
- must_not: 必須不匹配這些條件才能被包含進來, 是對must的取反操作,與SQL中的 != 或者<> 等價, where status != 0
- should 至少有一個語句要匹配, 與 SQL中的 OR 等價,是一個數組,可以有多個值,如果滿足這些語句中的任意語句,將增加_score的值, should的作用:or邏輯,如果滿足條件評分_score更高
- filter:必須匹配,以過濾模式來進行。這些語句對評分沒有貢獻,只是根據過濾標準來排除或包含文檔, filter只是簡單的數據過濾,并不影響評分
- minimum_should_match
bool 查詢會為每個文檔計算相關度評分 _score ,再將所有匹配的 must 和 should 語句的分數 _score 求和,最后除以 must 和 should 語句的總數。
must_not 語句不會影響評分;它的作用只是將不相關的文檔排除。
所有must語句必須匹配,所有must_not語句都必須不匹配,經測試至少有一個should需要匹配的(在should中寫兩個條件,每天條件都不滿足條件,結果沒有任何文檔滿足),當沒有 must 語句的時候,至少有一個 should 語句必須匹配。
GET /shop/goods/_search {"query": {"bool": {"must": [{"term": {"quantity": {"value": 999}}}], "must_not": [{"term": {"quantity": {"value": 9267}}}],"should": [{"term": {"is_discount": {"value": true}}}],"filter": {"range": {"price": {"gte": 7777,"lte": 9999}}}}} } // filter中也可以嵌套bool查詢,這樣內部的bool查詢就不參與評分了 // bool中的must must_not should 等會計算評分的,如果不希望計算評分,可將bool放入到filter中,這樣既不計算評分又可以使用bool中的邏輯 // 直接使用bool中的filter和將bool再次嵌入到filter中都不計算評分 GET /shop/goods/_search {"query": {"bool": {"must": { "match": { "title": "how to make millions" }},"must_not": { "match": { "tag": "spam" }},"should": [{ "match": { "tag": "starred" }}],"filter": {"bool": { "must": [{ "range": { "date": { "gte": "2014-01-01" }}},{ "range": { "price": { "lte": 29.99 }}}],"must_not": [{ "term": { "category": "ebooks" }}]}}}} }// 就像我們能控制 match 查詢的精度 一樣,我們可以通過 minimum_should_match 參數控制需要匹配的 // should 語句的數量, 它既可以是一個絕對的數字,又可以是個百分比: // 這個查詢結果會將所有滿足以下條件的文檔返回: // title 字段包含 "brown" AND "fox" 、 "brown" AND "dog" 或 "fox" AND "dog" 。 // 如果有文檔包含所有三個條件,它會比只包含兩個的文檔更相關。 GET /my_index/my_type/_search {"query": {"bool": {"should": [{ "match": { "title": "brown" }},{ "match": { "title": "fox" }},{ "match": { "title": "dog" }}],"minimum_should_match": 2 }} }// boost 參數被用來提升一個語句的相對權重( boost 值大于 1 )或降低相對權重( boost 值處于 0 到 1 之間), // 但是這種提升或降低并不是線性的,換句話說,如果一個 boost 值為 2 ,并不能獲得兩倍的評分 _score 。 // 通過指定 boost 來控制任何查詢語句的相對的權重, boost 的默認值為 1 ,大于 1 會提升一個語句的相對權重。 // 更高的 boost 值為我們帶來更高的評分 _score GET /_search {"query": {"bool": {"must": {"match": { "content": {"query": "full text search","operator": "and"}}},"should": [{ "match": {"content": {"query": "Elasticsearch","boost": 3 }}},{ "match": {"content": {"query": "Lucene","boost": 2 }}}]}} }過濾查詢:不需要評分,性能更好,對結果進行緩存
評分查詢:需要評分,評分比較費力,不對結果進行緩存
如何選擇查詢與過濾? 通常的規則是,使用查詢(query)語句來進行 全文搜索或者其它任何需要影響相關性得分的搜索。除此以外的情況都使用過濾(filters)。
aggs
聚合操作,類似SQL中的Group By, 支持的聚合類型有avg, min, max, sum, rang 等,也可以對地理位置進行聚合
如果要對一個字段進行聚合,要保證這個字段的fielddata設置為true
PUT /{index}/_mapping/{type} {"properties": {"FILED": {"type": "text","fielddata": true}} } // 統計數組中每個元素出現的次數,中文有問題,現在中文分詞是按單個字分詞的,估計需要指定對該字段不分詞 GET /shop/goods/_search {"aggs": {"xxx": {"terms": {"field": "colors","size": 10}}} }// aggs可以嵌套在aggs中使用 // 嵌套聚合,分級匯總,在聚合中可以進行再聚合,意思是對分組的文檔進行其他聚合,而不是對聚合結果進行處理 GET /shop/goods/_search {"aggs": {"xxx": {"terms": {"field": "colors","size": 10},"aggs": {"yyy": {"avg": {"field": "price"}}}}} }_mget
multi-get,通過docs數組作為參數指定多個doc來獲取多個文檔,每個doc可以分別指定索引、類型、id,文檔或者api中必須包含index/type/id
// 路徑中不包含index、type、id GET /_mget {"docs" : [{"_index" : "shop","_type" : "goods","_id" : 2},{"_index" : "account","_type" : "users","_id" : 1,"_source": "nickname"}] }// 路徑中包含index、type, 如果參數中沒有指定index、type就使用路徑中的,如果參數中明確指定了,就使用參數中的索引和類型 GET /{index}/{type}/_mget {"docs" : [{ "_id" : 2 },{ "_type" : "account", "_id" : 1 }] }// 路徑中指定了索引和類型,通過ids數組指定多個id值 GET /{index}/{type}/_mget' {"ids" : [ "2", "1" ] }_bulk
批量操作:將多個操作封裝成一個操作,一次執行多個動作(create,index, update以及delete),并返回每個執行結果.
可以通過_bulk來執行批量插入、批量更新等操作
POST _bulk的請求主體的格式稍微有些不同:
{ action: { metadata }}\n { request body }\n { action: { metadata }}\n { request body }\n ...它通過換行符(\n)連接到一起,最后一行也要有\n,每行一定要以換行符(\n)結尾, 包括最后一行 。這些換行符被用作一個標記,可以有效分隔行,這些行不能包含未轉義的換行符,因為他們將會對解析造成干擾
- action 必須是以下選項之一:
- create:如果文檔不存在,那么就創建它, 相當于 PUT /{index}/{type}/{id}/_create
- index:創建一個新文檔或者替換一個現有的文檔, 相當于 PUT /{index}/{type}/{id}
- update:部分更新一個文檔, 即局部更新文檔中的個別字段,相當于 /{index}/{type}/{id}/_update
- delete:刪除一個文檔,刪除操作不需要指定請求體,delete操作沒有請求體,它緊接著另一個行為;記得最后一個換行符
- metadata 每個動作需要的參數,json格式的,應該指定被索引、創建、更新或者刪除的文檔的_index,_type和 _id
每個子請求都是獨立執行,因此某個子請求的失敗不會對其他子請求的成功與否造成影響。 如果其中任何子請求失敗,最頂層的 error 標志被設置為 true ,并且在相應的請求報告出錯誤明細
這也意味著 bulk 請求不是原子的: 不能用它來實現事務控制。每個請求是單獨處理的,因此一個請求的成功或失敗不會影響其他的請求
我的微信公眾號:
總結
以上是生活随笔為你收集整理的Elasticsearch入门教程(五):Elasticsearch查询(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 彻底解决 webpack 打包文件体积过
- 下一篇: 格力美的,谁代表中国制造的未来