1. 程式人生 > >ElasticSearch DSL 查詢

ElasticSearch DSL 查詢

> **公號:碼農充電站pro** > **主頁:** **DSL**(Domain Specific Language)查詢也叫做 **Request Body** 查詢,它比 **URI 查詢**更高階,能支援更復雜的查詢。 ### 1,分頁 預設情況下,查詢按照算分排序,返回前 10 條記錄。 ES 也支援分頁,分頁使用 [from-size](https://www.elastic.co/guide/en/elasticsearch/reference/7.0/search-request-from-size.html): - **from**:從第幾個文件開始返回,預設為 0。 - **size**:返回的文件數,預設為 10。 示例: ```shell POST /index_name/_search { "from":10, "size":20, "query":{ "match_all": {} } } ``` #### 1.1,深度分頁問題 ES 是一個分散式系統,資料儲存在多個分片中,那麼查詢時就需要查詢多個分片。 比如一個查詢 `from = 990; size = 10`,那麼 ES 需要在每個分片上都獲取 1000 個文件: ![](https://img-blog.csdnimg.cn/20210120232414669.png) 然後通過 **Coordinating** 節點彙總結果,最後再通過排序獲取前 1000 個文件。 這種方式,當頁數很深的時候,就會佔用很多記憶體,從而給 ES 叢集帶來很大的開銷,這就是**深度分頁問題**。 因此,ES 為了避免此類問題帶來的巨大開銷,有個預設的限制 [index.max_result_window](https://www.elastic.co/guide/en/elasticsearch/reference/7.10/index-modules.html),`from + size` 必須小於等於 10000,否則就會**報錯**。 比如: ```shell POST index_name/_search { "from": 10000, # 報錯 "size": 1, "query": { "match_all": {} } } POST index_name/_search { "from": 0, # 報錯 "size": 10001, "query": { "match_all": {} } } ``` 為了解決深度分頁問題,ES 有兩種解決方案:**Search After** 和 **Scroll**。 #### 1.2,Search After [Search After](https://www.elastic.co/guide/en/elasticsearch/reference/7.10/paginate-search-results.html#search-after) 通過實時獲取下一頁的文件資訊來實現,使用方法: - 第一步搜尋需要指定 **sort**,並且保證值是唯一的(通過sort by id 來保證)。 - 隨後的搜尋,都使用上一次搜尋的最後一個文件的 sort 值進行搜尋。 **Search After** 的方式不支援指定頁數,只能一頁一頁的往下翻。 **Search After** 的原理: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210121000008616.png) 示例: ```shell # 插入一些資料 DELETE users POST users/_doc {"name":"user1","age":10} POST users/_doc {"name":"user2","age":11} POST users/_doc {"name":"user2","age":12} POST users/_doc {"name":"user2","age":13} # 第一次搜尋 POST users/_search { "size": 1, # size 值 "query": { "match_all": {} }, "sort": [ {"age": "desc"} , {"_id": "asc"} # sort by id ] } # 此時返回的文件中有一個 sort 值 # "sort" : [13, "4dR-IHcB71-f4JZcrL2z"] # 之後的每一次搜尋都需要用到上一次搜尋結果的最後一個文件的 sort 值 POST users/_search { "size": 1, "query": { "match_all": {} }, "search_after": [ # 上一次搜尋結果的最後一個文件的 sort 值放在這裡 13, "4dR-IHcB71-f4JZcrL2z"], "sort": [ {"age": "desc"} , {"_id": "asc"} ] } ``` #### 1.3,Scroll [Scroll](https://www.elastic.co/guide/en/elasticsearch/reference/7.10/paginate-search-results.html#scroll-search-results) 通過建立一個**快照**來實現,方法: - 每次查詢時,輸入上一次的 `Scroll Id`。 **Scroll** 方式的缺點是,當有新的資料寫入時,**新寫入的資料無法被查到**(第一次建立快照時有多少資料,就只能查到多少資料)。 示例: ```shell # 寫入測試資料 DELETE users POST users/_doc {"name":"user1","age":10} POST users/_doc {"name":"user2","age":20} # 第一次查詢前,先建立快照,快照存在時間為 5 分鐘,一般不要太長 POST /users/_search?scroll=5m { "size": 1, "query": { "match_all" : {} } } # 返回的結果中會有一個 _scroll_id # 查詢 POST /_search/scroll { "scroll" : "1m", # 快照的生存時間,這裡是 1 分鐘 "scroll_id" : "xxx==" # 上一次的 _scroll_id 值 } # 每次的查詢結果都會返回一個 _scroll_id,供下一次查詢使用 # 所有的資料被查完以後,再查詢就得不到資料了 ``` #### 1.4,不同分頁方式的使用場景 分頁方式共 4 種: - 普通查詢(不使用分頁):需要實時獲取頂部的部分文件。 - From-Size(普通分頁):適用於非深度分頁。 - Search After:需要深度分頁時使用。 - Scroll:需要全部文件,比如匯出全部資料。 ### 2,排序 ES 預設使用算分進行排序,我們可以使用 [sort-processor](https://www.elastic.co/guide/en/elasticsearch/reference/current/sort-processor.html)(不需要再計算算分)來指定排序規則;可以對某個欄位進行排序,最好只對**數字型**和**日期型**欄位排序。 示例: ```shell POST /index_name/_search { "sort":[{"order_date":"desc"}], # 單欄位排序 "query":{ "match_all": {} } } POST /index_name/_search { "query": { "match_all": {} }, "sort": [ # 多欄位排序 {"order_date": {"order": "desc"}}, {"_doc":{"order": "asc"}}, {"_score":{ "order": "desc"}} # 如果不指定 _score,那麼算分為 null ] } ``` 對 **text** 型別的資料進行排序會發生錯誤,可以通過開啟 fielddata 引數(一般**不建議這麼做**),來對 **text** 型別進行排序: ```shell # 開啟 text的 fielddata PUT index_name/_mapping { "properties": { "customer_full_name" : { # 欄位名稱 "type" : "text", "fielddata": true, # 開啟 fielddata "fields" : { "keyword" : { "type" : "keyword", "ignore_above" : 256 } } } } } ``` ### 3,欄位過濾 可以使用 `_source` 設定需要返回哪些欄位。示例: ```shell POST /index_name/_search { "_source":["order_date", "xxxxx"], "query":{ "match_all": {} } } ``` `_source` 中可以使用萬用字元,比如 `["name*", "abc*"]`。 ### 4,指令碼欄位 可以使用指令碼進行簡單的表示式運算。 ```shell POST /index_name/_search { "script_fields": { # 固定寫法 "new_field": { # 新的欄位名稱 "script": { # 固定寫法 "lang": "painless", # 固定寫法 "source": "doc['order_date'].value+'hello'" # 指令碼語句 } } }, "query": { "match_all": {} } } ``` ### 5,查詢與過濾 查詢會有相關性算分;過濾不需要進行算分,可以利用快取,效能更好。 參考[這裡](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-filter-context.html)。 ### 6,全文字查詢 [全文字](https://www.elastic.co/guide/en/elasticsearch/reference/current/full-text-queries.html)(Full text)查詢會對搜尋字串進行**分詞處理**。 全文字查詢有以下 9 種: 1. [intervals 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-intervals-query.html):可以對匹配項的順序和接近度進行細粒度控制。 2. [match 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html):全文字查詢中的標準查詢,包括模糊匹配、短語和近似查詢。 3. [match_bool_prefix 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-bool-prefix-query.html): 4. [match_phrase 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html): 5. [match_phrase_prefix 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase-prefix.html): 6. [multi_match 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html): 7. [common terms 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-common-terms-query.html): 8. [query_string 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html): 9. [simple_query_string 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html): #### 6.1,Match 查詢 **Match** 查詢是全文搜尋的標準查詢,與下面的幾種查詢相比,更加強大,靈活性也更大,最常使用。 [Match 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query.html)會先對輸入字串進行分詞,然後對每個詞項進行底層查詢,最後將結果合併。 例如對字串 "**Matrix reloaded**" 進行查詢,會查到包含 "Matrix" 或者 "reloaded" 的所有結果。 ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210117172328528.png?) 示例: ```shell POST index_name/_search { "query": { "match": { "title": "last christmas" # 表示包含 last 或 christmas } } } POST index_name/_search { "query": { "match": { "title": { # 表示包含 last 且 包含 christmas,不一定挨著 "query": "last christmas", "operator": "and" } } } } ``` #### 6.2,Match Phrase 查詢 使用 [match_phrase](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-match-query-phrase.html) 關鍵字。示例: ```shell POST index_name/_search { "query": { "match_phrase": { "title":{ "query": "one love" # "one love" 相當於一個單詞 } } } } POST index_name/_search { "query": { "match_phrase": { "title":{ "query": "one love", "slop": 1 # "one" 和 "love" 之間可以有 1 個字元 } } } } ``` #### 6.3,Query String 查詢 使用 [query_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html) 關鍵字。示例: ```shell POST index_name/_search { "query": { "query_string": { "default_field": "name", # 預設查詢欄位,相當於 URI 查詢中的 df "query": "Ruan AND Yiming" # 可以使用邏輯運算子 } } } # 多 fields 與 分組 POST index_name/_search { "query": { "query_string": { "fields":["name","about"], # 多個 fields "query": "(Ruan AND Yiming) OR (Java AND Elasticsearch)" # 支援分組 } } } POST index_name/_search { "query":{ "query_string":{ "fields":["title","year"], "query": "2012" } } } ``` #### 6.4,Simple Query String 查詢 使用 [simple_query_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-simple-query-string-query.html) 關鍵字。 特點: - **query** 欄位中不支援 `AND OR NOT`,會當成普通字串。 - `AND` 用 `+` 替代 - `OR` 用 `|` 替代 - `NOT` 用 `-` 替代 - Term 之間預設的關係是 `OR`,可以指定 `default_operator` 來修改。 示例: ```shell # Simple Query 預設的 operator 是 OR POST index_name/_search { "query": { "simple_query_string": { "query": "Ruan AND Yiming", # 這裡的 AND 會當成普通的字串 "fields": ["name"] } } } POST index_name/_search { "query": { "simple_query_string": { "query": "Ruan Yiming", "fields": ["name"], "default_operator": "AND" } } } GET index_name/_search { "query":{ "simple_query_string":{ "query":"Beautiful +mind", "fields":["title"] } } } ``` #### 6.5,Multi-match 查詢 一個字串在多個欄位中查詢的情況,如何匹配最終的結果。(還有一個 **dis-max** 查詢也是針對這種情況的) 一個字串在多個欄位中查詢的情況,Multi-match 有 6 種處理方式,如下: - **best_fields**:最終得分為**分數最高**的那個欄位,預設的處理方式。 - **most_fields**:算分相加。不支援 **AND** 操作。 - **cross_fields**:跨欄位搜尋,將一個查詢字串在**多個欄位**(就像一個欄位)上搜索。 - **phrase**: - **phrase_prefix**: - **bool_prefix**: 示例: ```shell POST index_name/_search { "query": { "multi_match" : { # multi_match 查詢 "query": "brown fox", # 查詢字串 "type": "best_fields", # 處理方式 "fields": [ "subject", "message" ], # 在多個欄位中查詢,fields 是一個數組 "tie_breaker": 0.3 } } } ``` ### 7,Term 查詢 [Term 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/term-level-queries.html)與**全文字**查詢不同的是,Term 查詢不會對查詢字串進行分詞處理,Term 查詢會在欄位匹配**精確值**。 Term 查詢輸入字串作為一個整體,在倒排索引中查詢匹配的詞項,並且會計算**相關性評分**。 **Term 查詢**包括以下 11 種: 1. [exists 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-exists-query.html) 2. [fuzzy 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-fuzzy-query.html) 3. [ids 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-ids-query.html) 4. [prefix 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html) 5. [range 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html) 6. [regexp 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html) 7. [term 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-term-query.html):如果某個文件的指定欄位包含某個**確切值**,則返回該文件。 8. [terms 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-query.html) 9. [terms_set 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-set-query.html) 10. [type 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-type-query.html) 11. [wildcard 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-wildcard-query.html) #### 7.0,結構化資料與查詢 結構化查詢是對**結構化資料**的查詢,可以使用 **Term 語句**進行查詢。 結構化資料有著**固定的格式**,包括: - 日期:日期比較,日期範圍運算等。 - 布林值:邏輯運算。 - 數字:數字大小比較,範圍比較等。 - 某些文字資料:比如標籤資料,關鍵詞等。 結構化查詢是對結構化資料的邏輯運算,運算結果只有“是”和“否”。 #### 7.1,term 查詢 如果某個文件的指定欄位**包含**某個**確切值**,則返回該文件。 ##### 1,示例 1 精確匹配 下面舉一個 term 查詢的例子,首先插入一個文件: ```shell POST /products/_bulk { "index": { "_id": 1 }} { "productID" : "XHDK-A-1293-#fJ3","desc":"iPhone" } ``` 該文件插入時,會使用**預設的分詞器**進行分詞處理。 使用 term 查詢: ```shell POST /products/_search { "query": { "term": { "desc": { # "value": "iPhone" # 會對 iPhone 精確匹配查詢。 # 文件插入時,iPhone 變成了 iphone # 所以查 iPhone 查不到任何內容 "value":"iphone" # 查 iphone 能查到 } } } } ``` ***keyword 子欄位*** ES 預設會對 **text** 型別的資料建立一個 **keyword** 子欄位,用於精確匹配,這稱為 ES 的**多欄位屬性**。 **keyword 子欄位**將原始資料原封不動的儲存了下來。 可以通過 **mapping** 檢視,如下所示: ```shell "desc" : { # 欄位名稱 "type" : "text", # text 資料型別 "fields" : { "keyword" : { # keyword 子欄位 "type" : "keyword", # keyword 子型別 "ignore_above" : 256 } } } ``` 下面使用 **keyword** 子欄位進行查詢: ```shell POST /products/_search { "query": { "term": { "desc.keyword": { # 在 desc 欄位的 keyword 子欄位中查詢 "value": "iPhone" # 能查到 //"value":"iphone" # 查不到 } } } } ``` ##### 2,示例 2 查詢布林值 **term 查詢**有算分: ```shell POST index_name/_search { "query": { # 固定寫法 "term": { # term 查詢,固定寫法 "avaliable": true # 查詢 avaliable 欄位的值為 true 的文件 } } } ``` 如果不需要算分,可以使用 [constant_score 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html),示例: ```shell POST index_name/_search { "query": { "constant_score": { # constant_score 查詢,固定寫法 "filter": { # 固定寫法 "term": { # constant_score 包裝一個 term 查詢,就沒有了算分 "avaliable": true } } } } } ``` #### 7.2,range 查詢 [range 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-range-query.html)中有幾個常用的比較運算: | 運算子 | 含義 | |--|--| | gt | 大於 | | gte | 大於等於 | | lt | 小於 | | lte | 小於等於 | ##### 1,數字型別 range 查詢 示例: ```shell POST index_name/_search { "query": { # 固定寫法 "range": { # range 查詢 "age": { # 欄位名稱 "gte": 10, # 10 <= age <= 20 "lte": 20 } } } } ``` ##### 2,日期型別 range 查詢 對於日期型別有幾個常用的符號: | 符號 | 含義 | |--|--| | y | 年 | | M | 月 | | w | 周 | | d | 天 | | H / h | 小時 | | m | 分鐘 | | s | 秒 | | now | 現在 | 示例: ```shell POST index_name/_search { "query" : { # 固定寫法 "range" : { # range 查詢 "date" : { # 欄位名稱 "gte" : "now-10y" # 10年之前 } } } } ``` #### 7.3,exists 查詢 **exists 語句**可以判斷文件是否存在**某個欄位**。 搜尋存在某個欄位的文件,示例: ```shell POST index_name/_search { "query" : { "exists": { # 存在 date 欄位的文件 "field": "date" } } } ``` 搜尋不存在某個欄位的文件,需要使用[布林查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html)。 示例: ```shell POST index_name/_search { "query": { "bool": { # 布林查詢 "must_not": { # 不存在 "exists": { # 不存在 date 欄位的文件 "field": "date" } } } } } ``` #### 7.4,terms 查詢 **terms 語句**用於處理多值查詢,相當於一個多值版的 **term 語句**,可以一次查詢多個值。 示例: ```shell POST index_name/_search { "query": { "terms": { # terms 查詢 "productID.keyword": [ # 欄位名稱 "QQPX-R-3956-#aD8", # 多個值 "JODL-X-1937-#pV7" ] } } } ``` ### 8,複合查詢 [複合查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/compound-queries.html)(Compound)能夠包裝其他**複合查詢**或**葉查詢**,以組合其結果和分數,更改其行為或者將查詢轉成**過濾**。 複合查詢有以下 5 種: - [bool 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html) - [boosting 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-boosting-query.html) - [constant_score 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html) - [dis_max 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-dis-max-query.html) - [function_score 查詢](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html) #### 8.1,bool 查詢 **bool 查詢**是一個或**多個子查詢**的組合,共包含以下 4 種子句: - **must**:必須匹配,**屬於查詢**,貢獻算分。 - **filter**:必須匹配,**屬於過濾器**,不貢獻算分。 - **should**:選擇性匹配,只要有一個條件匹配即可,**屬於查詢**,貢獻算分。 - **must_not**:必須不匹配,**屬於過濾器**,不貢獻算分。 **bool 查詢**的多個子句之間**沒有順序之分**,並且**可以巢狀**。 示例: ```shell POST index_name/_search { "query": { "bool" : { "must" : { "term" : { "user.id" : "kimchy" } }, "filter": { "term" : { "tags" : "production" } }, "must_not" : { "range" : { "age" : { "gte" : 10, "lte" : 20 } } }, "should" : [ # 是一個數組 { "term" : { "tags" : "env1" } }, { "term" : { "tags" : "deployed" } } ], "minimum_should_match" : 1, "boost" : 1.0 } } } ``` #### 8.2,boosting 查詢 **boosting 查詢**會給不同的查詢條件分配不同的級別(**positive / negative**),不同的級別對算分有著不同的印象,從而影響最終的算分。 **positive** 級別會對算分有**正面影響**, **negative** 級別會對算分有**負面影響**。 我們可以使用 **boosting 查詢**給某些文件**降級**(降低算分),而不是將其從搜尋結果中**排除**。 示例: ```shell GET index_name/_search { "query": { "boosting": { # boosting 查詢 "positive": { # positive 級別 "term": { # 匹配 apple 的會對算分有正面影響 "text": "apple" } }, "negative": { # negative 級別 "term": { # 匹配這個的會對算分有負面影響 "text": "pie tart fruit crumble tree" } }, "negative_boost": 0.5 # 降級的力度 } } } ``` #### 8.3,constant_score 查詢 **constant_score 查詢**可以將查詢轉成一個**過濾**,可以避免**算分**(降低開銷),並有效利用快取(提高效能)。 示例: ```shell POST /index_name/_search { "query": { "constant_score": { # constant_score 查詢 "filter": { # 過濾器,固定寫法 "term": { # 包裝了一個 term 查詢,將 term 查詢轉成了過濾 "productID.keyword": "XHDK-A-1293-#fJ3" } } } } } ``` #### 8.4,dis_max 查詢 一個字串在多個欄位中查詢的情況,如何匹配最終的結果。(還有一個 **Multi-match** 查詢也是針對這種情況的) 示例: ```shell POST index_name/_search { "query": { "bool": { "should": [ # should 語句會綜合所有的欄位的分數,最終給出一個綜合分數 { "match": { "title": "Brown fox" }}, { "match": { "body": "Brown fox" }} ] } } } POST index_name/_search { "query": { "dis_max": { # dis_max 語句不會綜合所有欄位的分數,而把每個欄位單獨來看 "queries": [ # 最終結果是所有的欄位中分數最高的 { "match": { "title": "Quick pets" }}, { "match": { "body": "Quick pets" }} ] } } } ``` #### 8.5,function_score 查詢 **function_score 查詢**可以在查詢結束後,對每一個匹配的文件進行**重新算分**,然後再根據新的算分進行排序。 它提供了以下 5 種算分函式: - **script_score**:自定義指令碼。 - **weight**:為文件設定一個權重。 - **random_score**:隨機算分排序。 - **field_value_factor**:使用該數值來修改算分。 - **decay functions**: gauss, linear, exp:以某個欄位為標準,距離某個值越近,得分越高。 ##### 1,field_value_factor 示例 首先插入測試資料: ```shell DELETE blogs PUT /blogs/_doc/1 { "title": "About popularity", "content": "In this post we will talk about...", "votes": 0 } PUT /blogs/_doc/2 { "title": "About popularity", "content": "In this post we will talk about...", "votes": 100 } PUT /blogs/_doc/3 { "title": "About popularity", "content": "In this post we will talk about...", "votes": 1000000 } ``` 查詢示例1: **新的算分 = 老的算分 * 投票數** ```shell POST /blogs/_search { "query": { "function_score": { "query": { "multi_match": { # 該查詢會有一個算分 "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { # 最終的算分要乘以 votes 欄位的值 "field": "votes" } } } } ``` 上面這種演算法當出現這兩種情況的時候,會出現問題: - 投票數為 0 - 投票數特別大 查詢示例2,引入**平滑函式**: **新的算分 = 老的算分 * 平滑函式(投票數)** ```shell POST /blogs/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p" # 在原來的基礎上加了一個平滑函式 } # 新的算分 = 老的算分 * log(1 + 投票數) } } } ``` **平滑函式**有下面這些: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210119104333757.png) 查詢示例3,引入 **factor** : **新的算分 = 老的算分 * 平滑函式(factor * 投票數)** ```shell POST /blogs/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p" , "factor": 0.1 } } } } ``` 引入 **factor** 之後的算分曲線: ![在這裡插入圖片描述](https://img-blog.csdnimg.cn/20210119104829380.png) ##### 2,Boost Mode 和 Max Boost 引數 Boost Mode: - Multiply:算分與函式值的乘積。 - Sum:算分與函式值的和。 - Min / Max:算分與函式值的最小/最大值。 - Replace:使用函式值替代算分。 Max Boost 可以將算分控制在一個最大值。 示例: ```shell POST /blogs/_search { "query": { "function_score": { "query": { "multi_match": { "query": "popularity", "fields": [ "title", "content" ] } }, "field_value_factor": { "field": "votes", "modifier": "log1p" , "factor": 0.1 }, "boost_mode": "sum", "max_boost": 3 } } } ``` ##### 3,random_score 示例 示例: ```shell POST /blogs/_search { "query": { "function_score": { "random_score": { # 將原來的查詢結果隨機排序 "seed": 911119 # 隨機種子 } } } } ``` (本節完。) --- **推薦閱讀:** [ElasticSearch 查詢](https://www.cnblogs.com/codeshell/p/14389415.html) [ElasticSearch URI 查詢](https://www.cnblogs.com/codeshell/p/14429420.html) [ElasticSearch 文件及操作](https://www.cnblogs.com/codeshell/p/14429409.html) [ElasticSearch 分詞器](https://www.cnblogs.com/codeshell/p/14389403.html) [ElasticSearch 搜尋引擎概念簡介](https://www.cnblogs.com/codeshell/p/14389383.html) --- *歡迎關注作者公眾號,獲取更多技術乾貨。* ![碼農充電站pro](https://img-blog.csdnimg.cn/20200505082843773.png?#pic