日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Query DSL

發布時間:2025/3/17 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Query DSL 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

"ES提供了基于JSON的查詢DSL,它由兩種語句組成:

  • 葉子查詢(Leaf Query):查詢特定字段的特定值,比如match, term, range查詢,這些查詢可以單獨使用。
  • 復合查詢(Compound Query):復合查詢包裝其他葉子查詢和復合查詢,以邏輯運算的方式(比如bool,dis_max查詢)連接多個查詢,或更改它們的行為(比如,constant_score查詢)

依據它們是在查詢上下文(query context)還是過濾上下文(filter context),查詢語句的行為也有所不同。

查詢和過濾上下文

查詢上下文

在查詢上下文解決的是這種問題:“此文檔與此查詢的匹配程度如何?”,除了決定文檔是否匹配外,查詢語句還會計算一個_score字段,表示該文檔相對其他文檔的匹配程度。

位于query參數下的語句,處于查詢上下文。

過濾查詢

過濾上下文解決的是這種問題:“此文檔是否匹配該查詢”,回答只有是或者否,不會計算相關性分值。過濾上下文主要用于過濾結構化的數據,比如:

  • 這個時間是否屬于2015-2016年之間
  • status字段的值是否是1

ES會緩存經常使用的查詢,以提升性能。

位于filter參數下的語句,處于過濾上下文中。比如在bool查詢中的filter或must_not參數,在constant_score查詢中的filter參數,或filter聚合。

下面的示例展示搜索API中,在查詢上下文和過濾上下文中的語句。這條查詢會匹配滿足下列條件的文檔:

  • title字段包含單詞search
  • content字段包含單詞elasticsearch
  • satus字段指就是published
  • publish_date字段的日期大于等于2015.1.1
GET /_search {"query": { // 查詢上下文"bool": {"must":[{"match": {"title": "search"}},{"match": {"content": "elasticsearch"}}],"filter":[ // 過濾上下文{"term": {"status": "published"}},{"range": {"publish_data": {"gte": "2015-01-01"}}}]}} }

說明:

  • bool和match語句用在查詢上下文中,這意味著他們被用來評估每個文檔的匹配程度(分值)。
  • term和range語句用在過濾上下文中,它們會過濾掉不匹配的文檔,但是不會影響匹配文檔的分值

匹配所有

match_all查詢,匹配所有文檔,每個文檔_score值為1:

GET {index}/_search {"query": {"match_all": {}} }

與之相反的是match_none,不匹配任何文檔

全文查詢

全文查詢允許你搜索分詞后的文本字段,比如電子郵件的內容。包括:

  • match :全文查詢的標準方式,包括模糊匹配(fuzzing),短語或鄰近查詢。
  • match_phrase :類似match,但只用于精確匹配短語或單詞鄰近匹配
  • match_phrase_prefix:同上,但是只對最后一個單詞進行通配符搜索
  • match_bool_prefix:創建一個bool查詢,對每個詞條創建一個term查詢,最后一個詞條除外,該詞條作為prefix查詢匹配
  • multi_match:match查詢的多字段形式
  • common詞條查詢:相對專門的查詢,適用于不常用的單詞
  • query_string查詢:支持緊湊的Lucene查詢字符串語法,支持在單個查詢字符串中指定AND|OR|NOT邏輯條件和多字段搜索。僅限專業用戶使用
  • simple_query_string查詢:比起query_string語法更簡單,更健壯,適用于普通用戶使用
  • intervals查詢:允許對匹配詞條的順序和鄰近度進行細粒度(fine-grained)的控制

match

我們先創建一條文檔:

POST twitter/_doc {"user": "ayhan","post_date": "2009-11-15T14:12:12","message": "let me out from here" }

基本用法:

GET twitter/_search {"query": {"match": {"message": "out me" // messag是搜索的字段,值是要查詢的字符串}} }

因此上述查詢的結果是message字段中包含詞條out, 或me的所有文檔。

match查詢會對提供的文本進行分詞,并構建布爾查詢。邏輯運算符operator默認是or,我們也可以手動設為and,來控制布爾語句。

GET twitter/_search {"query": {"match": {"message": {"query": "out me", // 指定查詢字符串"operator": "and" // 指定邏輯運算符}}} }

這樣查詢的結果是message字段中同時包含詞條out 和 me的所有文檔,范圍將大大縮小。

除了指定operator,我們還可以指定如下參數:

  • analyzer 指定分詞器
  • minimum_should_match,沒看懂
  • lenient :異常處理,是否忽略由數據類型錯誤導致的異常,默認false,比如使用文本查詢字符串來查詢數字字段
  • zero_terms_query:零項查詢,指定查詢詞條為空時的行為(比如指定的分詞器移除了所有詞條),其值為:
    • none,相當于match_none,默認值
    • all ,相當于match_all
  • cutoff frequency :指定文檔高低頻的分界線
  • synonyms 對于同義詞定義:ny, new york,相當于ny OR (new york)

match phrase

短語匹配,示例:

GET twitter/_search {"query": {"match_phrase": {"message": "huawei mate pro" // 查詢message字段包含huawei mate pro的文檔}} }

類似match查詢,短語匹配首先也會將查詢字符串解析為詞條列表,然后對這些詞條進行搜索。但是只保留同時包含所有詞條,且位置順序與搜索詞條一致,中間不夾雜其他單詞的文檔。

短語匹配是利用倒排索引中的位置信息實現的。

判斷文檔是否和短語huawei mate pro匹配,要同時滿足如下條件:

  • huawei、mate和pro必須全部出現
  • mate的位置比huawei大1
  • pro的位置比mate大2

multi_match

multi_match基于match查詢,但是支持查詢多個字段:

GET article/_search {"query": {"multi_match": {"query": "hello world", // 查詢字符串"fields": ["title", "content"] // 要查找的字段}} }

如果不指定具體字段,將查詢所有字段。multi_match查詢支持match查詢的所有參數。

通配符

fields參數可以支持通配符,比如:

"fields": [ "title", "*_name" ]

可以查詢title, first_name和last_name字段

字段權重

可以使用^標記,增大個別字段的權重:

"fields": ["title^3", "content"]

如此一來,title字段的權重3倍于content字段,這將會影響搜索結果中_score的打分(打分越高,排名越靠前),^標記的權重的值越大,對打分影響越大。

查詢方式

multi_match的查詢方式取決于type參數,默認值是best_fields,全部可選項及區別具體參考官網

best_fields

如果你想搜索多個單詞在某個字段中的最好匹配,best_fields最合適。例如,"huawei mate pro"出現在單個字段中,比"huawei"出現在一個字段,"mate pro"出現在另一個字段更有意義。

best_fields方式為每個字段創建一個match查詢,并包在一個dis_max查詢中,來找到單個最匹配的字段。比如:

GET /_search {"query": {"multi_match" : {"query": "brown fox","type": "best_fields","fields": [ "subject", "message" ],"tie_breaker": 0.3}} }

會這樣執行:

GET /_search {"query": {"dis_max": {"queries": [{ "match": { "subject": "brown fox" }},{ "match": { "message": "brown fox" }}],"tie_breaker": 0.3}} }

打分方式:通常情況下,best_fields使用匹配最好的字段的打分,但是如果指定了tie_breaker參數,則有所不同,具體查看官網。

注意:

best_fiels和most_fields方式都會為每個字段創建一個match查詢,因此operator和minimum_should_match參數將對每個字段單獨應用,這可能不是你想要的。比如:

GET /_search {"query": {"multi_match" : {"query": "Will Smith","type": "best_fields","fields": [ "first_name", "last_name" ],"operator": "and"}} }

將會以這樣的邏輯執行:

(+first_name:will +first_name:smith) | (+last_name:will +last_name:smith)

也就是說,如果一個文檔要匹配,必須在單個字段中出現查詢的所有詞條。

most_fields

如果查詢的多個字段的文本經過分詞處理后(不管以怎樣的方式),包含同樣的文本,那么most_fields方式最合適。比如,主字段的查詢結果可能包含同義詞,詞干,沒有變音符的詞條等(可以理解為關聯性較強的文檔)。第二個字段可能包含原始的查詢詞條(更準確,但是范圍更小,但是打分高)。通過合并這些字段的打分,我們可以匹配盡可能多的文檔(主字段),但是最接近的結果又可以獲得優先展示(第二個字段)。

如下查詢:

GET /_search {"query": {"multi_match" : {"query": "quick brown fox","type": "most_fields","fields": [ "main_filed", "strict_field" ]}} }

將會這樣執行:

GET /_search {"query": {"bool": {"should": [{ "match": { "main_filed": "quick brown fox" }},{ "match": { "strict_field": "quick brown fox" }}]}} }

打分方式:每個match語句的打分被加總,然后除以match語句的數量。

cross_fields

cross_fields方式特別適合要匹配多個字段的結構化文檔。比如,要從first_name和last_name字段中查詢"Will Smith",最匹配的應該是Will出現firs_name字段,而Smith出現在last_name字段。

一種處理這種查詢的方式是只需要將first_name和last_name索引到一個full_name字段。但是,這只能在索引時操作。而cross_fields方式嘗試在查詢時解決這種問題。它先將查詢字符串分詞為一個個詞條,然后在指定字段中查找每個詞條。

下面的查詢:

GET /_search {"query": {"multi_match" : {"query": "Will Smith","type": "cross_fields","fields": [ "first_name", "last_name" ],"operator": "and"}} }

將會這樣執行:

+(first_name:will last_name:will) +(first_name:smith last_name:smith)

也就是說,一個文檔如果要匹配,所有的詞條必須出現在至少一個字段中。

common

common查詢時可以將停用詞考慮在內,對于能提高查詢精度,影響查詢結果的停用詞是不錯的選擇,并且不會犧牲性能。

問題

查詢的每個詞條都有花銷。比如,搜索"The brown fox"將產生3次詞條查詢,也就是"the",“brown”,“fox”,每次查詢都要搜索索引中的所有文檔。對于"the"的查詢很可能會匹配到大量文檔,但是比起另外兩次查詢,"the"對于相關性的影響要小得多。

之前的方案是,忽略哪些高頻出現的詞條。也就是將"the"作為停用詞對待,這樣不僅能減少索引的大小,還可以較少需要執行查詢的詞條的數量。

這種方案的問題是,盡管停用詞對相關性的影響很小,但它們仍然很重要。如果移除了停用詞,不僅影響查詢的精度(比如,無法區分"happy"和"not happy"),甚至是丟失查詢結果("To be or not to be"壓根不會被搜到)。

解決方案

common查詢將要查詢的詞條分為兩組:重要的(比如,低頻詞條)和相對不重要的(比如,像停用詞這樣的高頻詞條)。

首先,查詢能匹配重要詞條的文檔,包含這類詞條的文檔相對較少并且對相關性影響較大。

然后,對不重要的詞條執行第二次查詢,這類詞條在文檔中高頻出現并且對相關性影響較小。但是,這里不會計算所有匹配文檔的相關性打分,只計算在第一次查詢中已經匹配的文檔。通過這種方式,高頻詞條可以改進相關性計算,卻不用付出過大的性能代價。

如果查詢只包含高頻詞條,那么每次查詢會以AND連接,也就是所有的詞條都需要。盡管單個詞條會匹配到大量文檔,但是詞條的聯合可以縮小范圍為最相關的文檔。不過,通過指定minimum_should_match,每次查詢也可以用OR連接,但是這種情況下,需要指定一個足夠大的值。

詞條是分布在高頻組還是低頻組,是基于cutoff_frequency,其可以指定為絕對頻率(>=1),或者是相對頻率(0.0 .. 1.0),高于設定值的屬于高頻詞條,反之低頻詞條。

注意:common不支持多字段查詢

示例

下面的示例中,文檔頻率大于0.1%的單詞(比如,“this"和"is”)視為common terms

GET /_search {"query": {"common": {"body": {"query": "this is bonsai cool","cutoff_frequency": 0.001}}} }

要匹配的詞條數可以通過以下參數控制:

  • minimum_should_match 指定低頻詞至少要匹配幾個
    • high_freq 指定高頻詞至少匹配幾個
    • low_freq 指定低頻詞至少匹配幾個
  • low_freq_operator(默認"or")
  • high_freq_oprator(默認"or")

對于低頻詞條,設置low_freq_operator為and,來要求所有詞條都滿足:

GET /_search {"query": {"common": {"body": { // 查詢body字段"query": "nelly the elephant as a cartoon","cutoff_frequency": 0.001,"low_freq_operator": "and"}}} }

以上相當于:

GET /_search {"query": {"bool": {"must": [{ "term": { "body": "nelly"}},{ "term": { "body": "elephant"}},{ "term": { "body": "cartoon"}}],"should": [{ "term": { "body": "the"}},{ "term": { "body": "as"}},{ "term": { "body": "a"}}]}} }

也可以通過minimum_should_match參數指定低頻詞(重要詞)出現的最小百分比,比如:

GET /_search {"query": {"common": {"body": {"query": "nelly the elephant as a cartoon","cutoff_frequency": 0.001,"minimum_should_match": 2}}} }

以上約等于:

GET /_search {"query": {"bool": {"must": {"bool": {"should": [{ "term": { "body": "nelly"}},{ "term": { "body": "elephant"}},{ "term": { "body": "cartoon"}}],"minimum_should_match": 2 // nelly、elephant、cartoon中至少匹配到兩個,才影響相關性}},"should": [{ "term": { "body": "the"}},{ "term": { "body": "as"}},{ "term": { "body": "a"}}]}} }

如果想同時指定低頻詞和高頻詞的匹配數,可以指定minimum_should_match的low_freq和high_freq:

GET /_search {"query": {"common": {"body": {"query": "nelly the elephant not as a cartoon","cutoff_frequency": 0.001,"minimum_should_match": {"low_freq" : 2,"high_freq" : 3}}}} }

以上相當于:

GET /_search {"query": {"bool": {"must": {"bool": {"should": [{ "term": { "body": "nelly"}},{ "term": { "body": "elephant"}},{ "term": { "body": "cartoon"}}],"minimum_should_match": 2 // 以上3個詞條至少匹配兩個}},"should": {"bool": {"should": [{ "term": { "body": "the"}},{ "term": { "body": "not"}},{ "term": { "body": "as"}},{ "term": { "body": "a"}}],"minimum_should_match": 3 // 以上四個詞條至少匹配3個}}}} }

如果為高頻詞指定了minimum_should_match,并且查詢字符串中只有高頻詞時:

GET /_search {"query": {"common": {"body": {"query": "how not to be","cutoff_frequency": 0.001,"minimum_should_match": {"low_freq" : 2,"high_freq" : 3}}}} }

以上相當于:

GET /_search {"query": {"bool": {"should": [{ "term": { "body": "how"}},{ "term": { "body": "not"}},{ "term": { "body": "to"}},{ "term": { "body": "be"}}],"minimum_should_match": "3<50%" // 老實說,我也沒看明白}} }

最后,common查詢也支持boost和analyzer參數。

simple_query_string

term查詢

term查詢是一種適用于結構化數據的精確查詢,它不會像全文檢索一樣對搜索做分詞。結構化數據包括日期,IP,價格,商品條碼等。注意:要避免對text字段使用term查詢(text字段的內容經過語義處理,可能發生變化)。

term

GET /_search {"query": {"term": {"user": { // 要查找的字段"value": "Kimchy", // 該字段要精確包含的值"boost": 1.0}}} }

terms

同term,但是可以搜索多個值:

GET /_search {"query" : {"terms" : {"user" : ["foo", "bar"],"boost" : 1.0}} }

以上只要user字段包含foo, 或者bar即可(Foo, bars不算)

復合查詢

constant_score

包裝一個過濾查詢,所有匹配的文檔會給予相同的打分1.0(因為過濾上下文不計算打分)

GET /_search {"query": {"constant_score" : {"filter" : {"term" : { "user" : "kimchy"}},"boost" : 1.2}} }

bool

匹配布爾連接的多個查詢,類別如下:

  • must 必須匹配,影響打分()
  • filter 必須匹配,但是忽略打分(0分)
  • should 應該匹配,影響打分
  • must_not 不能匹配(語句會在過濾上下文中執行,因此打分也會忽略(0分))類似于exclude

注意:must和should的打分會累加為匹配文檔最終打分

POST _search {"query": {"bool" : {"must" : {"term" : { "user" : "kimchy" }},"filter": {"term" : { "tag" : "tech" }},"must_not" : {"range" : {"age" : { "gte" : 10, "lte" : 20 }}},"should" : [{ "term" : { "tag" : "wow" } },{ "term" : { "tag" : "elasticsearch" } }],"minimum_should_match" : 1, // 是否是針對should生效?"boost" : 1.0}} }

另外,must, filter, must_not也可以使用列表的形式指定多個條件。

bool查詢中有一個match_all查詢,會給所有文檔打1.0分

GET _search {"query": {"bool": {"must": {"match_all": {}},"filter": {"term": {"status": "active"}}}} }

另外,constant_score和match_all是同樣的效果:

GET _search {"query": {"constant_score": {"filter": {"term": {"status": "active"}}}} }

dis_max

function_score

boosting

權重查詢,返回能夠匹配positive的文檔,并減小匹配negative文檔的打分

GET /_search {"query": {"boosting" : {"positive" : {"term" : {"text" : "apple"}},"negative" : {"term" : {"text" : "pie tart fruit crumble tree"}},"negative_boost" : 0.5}} }

總結

以上是生活随笔為你收集整理的Query DSL的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。