ElasticSearch 查詢DSL(Domain Specific Language便锨,領(lǐng)域特定語(yǔ)言),基于6.8.15版本
語(yǔ)法筆記吉捶。
- Query Context(查詢上下文): 除了判斷文檔是否匹配外夺鲜,查詢子句還會(huì)計(jì)算
_score
元數(shù)據(jù)字段中的相關(guān)性分?jǐn)?shù)。每個(gè)查詢子句要表達(dá)的含義是“此文檔與此查詢子句匹配程度如何呐舔?” - Filter Context(過濾器上下文):過濾上下文主要用于過濾結(jié)構(gòu)化數(shù)據(jù)币励,Elasticsearch 會(huì)自動(dòng)緩存常用的過濾器,以提高性能珊拼。每個(gè)查詢子句表達(dá)的含義是“此文檔是否與此查詢子句匹配食呻?”
Compounded Queries(混合查詢)
Boolean Query
通過must
、should
澎现、must_not
和 filter
組織查詢條件仅胞,形成一種或與非邏輯查詢。允許邏輯嵌套剑辫。
- must:必須滿足的條件干旧,相當(dāng)于 and
- should:滿足其中一個(gè)條件即可,相當(dāng)于 or
- must not:必須不滿足條件妹蔽,相當(dāng)于 not 椎眯,不會(huì)參與評(píng)分
- filter:與 must 含義相同,不參與評(píng)分
舉例:
// type 是低版本的概念胳岂,后續(xù)已經(jīng)被作廢编整。6.8可以填_doc 或者 不填寫
POST /users{/_doc}/_search
{
"query": {
"bool" : {
//注意這里的不同
//_name 字段給每個(gè)查詢條件起一個(gè)名字
//這樣在查詢記錄里就會(huì)多一個(gè) matched_queries 來指明命中了那些條件
"must" : {
"term" : {
"user.id" : {"query":"kimchy" ,"_name":"fist"}
}
},
"filter": {"term" : { "tags" : "production" } },
"must_not" : {"range" : {"age" : { "gte" : 10, "lte" : 20 }}},
"should" : [
{ "term" : { "tags" : "env1" } },
{ "term" : { "tags" : "deployed" } }
],
//表示,should中n個(gè)條件乳丰,必須滿足其中n個(gè)闹击,默認(rèn)為1
"minimum_should_match" : 1,
// 最終得分 = 分?jǐn)?shù) * boost
"boost" : 1.0
}
}
}
Boosting Query
POST /articles/_search
通過 positive
和 negative
兩種搜索條件的匹配,來正面(positive
)或負(fù)面(negative
)影響 _score
的計(jì)算成艘。
POST /articles/_search
{
"query": {
"boosting": {
//必須要滿足的條件
"positive": {
"match": {
"title": "Java"
}
},
//扣分條件赏半,滿足條件則最終分?jǐn)?shù) = positive 匹配得分 * negative_boost
"negative": {
"match": {
"title": "developer"
}
},
"negative_boost": 0.1
}
}
}
Constant Score Query
因?yàn)?code>filter查詢,并不會(huì)計(jì)算分?jǐn)?shù)淆两,因此這種方式可以為其查詢結(jié)果給出一個(gè)固定分?jǐn)?shù)断箫。
POST /articles/_search
{
"query": {
"constant_score": {
//這里必須是filter
"filter": {
"term": {
"title.keyword": "Java developer"
}
},
// filter 最終的得分為 1.2
"boost": 1.2
}
}
}
Dis Max Query (DisjunctionMaxQuery)
通過多個(gè)查詢條件匹配文檔,以匹配條件中最高分?jǐn)?shù)作為最終得分秋冰,其他非高分匹配的條件仲义,需要通過tie_breaker
來影響得分。
POST /articles/_search
{
"query": {
"dis_max": {
//標(biāo)識(shí)非最高分匹配命中,分?jǐn)?shù)需要 乘以 0.7
"tie_breaker": 0.7,
//用于指定 Constant Score Query 這種的固定分?jǐn)?shù)埃撵,constant_query 里面指定的優(yōu)先
"boost": 1.2,
//有多個(gè)匹配條件赵颅,假設(shè)第一匹配分?jǐn)?shù)最高
//最終得分 = 第一個(gè)匹配得分 + 第二個(gè)匹配得分 * 0.7
"queries": [
{"match": {"title": "Java developer"}},
{"match": {"content": "Java"}},
{"constant_score": {
"filter": {
"term": {
"title.keyword": "Java developer"
}
},
//這個(gè)比外面的boost優(yōu)先級(jí)高
"boost": 3
}}
]
}
}
}
Function Score Query
通過一些函數(shù)來計(jì)算最終的得分情況。
final_score = boost_mode(query_score,score_mode(fun_score_1...2))
- score_mode:multiply暂刘、sum饺谬、avg频丘、first腌巾、max、min
- boost_mode:multiply审葬、replace(特殊森缠,只使用func_score拔鹰,不用query_socre)、sum贵涵、avg列肢、max、min
- function:weight(不指定就是它)宾茂、field_value_factor(基于指定字段)例书、script_score(通過函數(shù)腳本)、衰減函數(shù) (linear刻炒、exp决采、guass) 和 random_score(0到1浮點(diǎn)隨機(jī)數(shù))
下面這個(gè)例子基于:
function: weight、field_value_factor
score_mode: sum
boost_mode: sum
POST /articles/_search
{
"query": {
"function_score": {
"boost":2,
//這里使用 match_all 不會(huì)打分去 boost = 2坟奥,所以 query_score = 2
"query": {"match_all": {}},
"functions": [
//符合次filter匹配的 fun_score_1 = size(假設(shè)10) * weight = 20
{
"filter": {
"term": {
"title.keyword": "Java developer"
}
},
"weight": 2,
"field_value_factor": {
"field": "size"
}
},
//符次filter條件的 fun_score_2 = weight = 2
{
"filter": {
"match":{
"content":"Spring"
}
},
"weight": 2
},
//符次filter條件的 fun_score_3 = weight = 1
{
"filter": {
"match":{
"content":"NIO"
}
},
"weight": 1
}
],
//functions 中多個(gè)計(jì)分方式树瞭,他們之間是通過累加的方式
//即 fun_score = sum(fun_score_1,fun_score_2,fun_score_3) = 23
"score_mode": "sum",
//最終得分 = sum(query_score,fun_score)
"boost_mode": "sum",
// 指定 functions 的最終打分不能超過 30 Math.min(fun_score,30)
"max_boost": 30
}
}
}
// script_score 使用,替代上面的 fun_score_1 中 field_value_factor 即可
"script_score": {
"script": {
"params": {
"a": 5,
"b": 1.2
},
"source": "params.a / Math.pow(params.b, doc['my-int'].value)"
}
}
Full Text Queries(全文本搜索)
match
將查詢文本分詞后爱谁,在指定字段上進(jìn)行匹配晒喷。
萊文斯坦距離:指兩個(gè)字符串之間,由一個(gè)轉(zhuǎn)成另一個(gè)所需的最少編輯操作次數(shù)访敌。
- 將一個(gè)字符替換成另一個(gè)字符
- 插入一個(gè)字符
- 刪除一個(gè)字符
POST /articles/_search
{
"query": {
"match": {
"content": {
//這個(gè)文本會(huì)被凉敲,下面的 analyzer
"query": "ja1a spr0ng",
"analyzer": "standard",
//表示分詞成term之后,查詢是通過and連接的寺旺,默認(rèn)是or
"operator": "and",
//表示是否忽略類型轉(zhuǎn)換錯(cuò)誤
//比如說通過 size 字段(數(shù)值類型)查詢傳了一個(gè) 字符串默認(rèn) false 會(huì)報(bào)錯(cuò)的
"lenient": "true",
//標(biāo)識(shí)是否啟用模糊查詢爷抓,使用 Levenshtein Edit Distance 萊文斯坦距離做模糊匹配
//默認(rèn)是0,標(biāo)識(shí)精確匹配
//AUTO表示 0-2 必須精確 3-5 支持最小編輯為1 5 以上最小編輯為 2
"fuzziness": "AUTO",
//模糊查詢時(shí)阻塑,term 的前 2 個(gè)必須一樣蓝撇,從第三個(gè)字符開始允許編輯
"prefix_length": 2,
//表示是否過濾掉停用次,默認(rèn)是none陈莽,如果期望不過濾使用 all
"zero_terms_query": "none",
//定義高頻詞渤昌,分?jǐn)?shù)表示虽抄,term 出現(xiàn)頻率 正數(shù)表示出現(xiàn)次數(shù)
//在 operator 為 and match 會(huì)被改寫成 bool 查詢邏輯,低頻次是一個(gè)must的邏輯独柑,高頻詞是should的邏輯迈窟,高頻詞會(huì)影響到最終的得分
"cutoff_frequency": 2
}
}
}
}
match_phrase
相比于match
,match_phrase
外強(qiáng)調(diào)了term
的位置忌栅,也就是要求匹配文本具有一定的語(yǔ)法順序车酣。可以用來做用戶輸入補(bǔ)全狂秘。
POST /articles/_search
{
"query": {
"match_phrase": {
"content": {
//Unity3d 和 DDL 這兩個(gè)詞必須存在骇径,并且順序先后出現(xiàn)
"query": "Unity3d DDL",
//表示 Unity3d 和 DDL 中間只能差一個(gè)詞
"slop": 1
}
}
}
}
match_phrase_prefix
與 match_phrase
一樣的躯肌,但最后一個(gè)詞可以只給前綴
{
"query": {
"match_phrase_prefix": {
"content": {
"query": "Spring Fr",
//這個(gè)參數(shù)者春??清女?
"max_expansions": 0
}
}
}
}
multi_match
文檔多字段匹配
POST /articles/_search
{
"query": {
"multi_match": {
"query": "spring",
//content^3^3 表示content字段匹配打分會(huì) 乘以 3
//titl* 表示模糊匹配字段钱烟,如果匹配不到會(huì)報(bào)錯(cuò)
"fields": ["content^3","titl*"]
}
}
}
common
common存在是為了提高,低頻次的匹配精度嫡丙,降低停用詞的影響但不排除停用詞拴袭。
在實(shí)際匹配過程中,如果停用詞參與了匹配那么曙博,那么結(jié)果會(huì)出現(xiàn)很多無關(guān)文檔拥刻,如果省略掉則會(huì)造成失語(yǔ)現(xiàn)象,如“no happy” no被去掉后可能就變成“haapy”父泳。這時(shí)候就可以用common
POST /articles/_search
{
"query": {
"common": {
"content": {
//實(shí)際會(huì)被解析成BooleanQuery
"query": "no Spring Framework",
"cutoff_frequency": 0.001,
//再and的情況下
//非停用詞是must邏輯
//停用詞是 should 邏輯
"low_freq_operator": "and"
}
}
},
"profile": "true"
}
Term-level queries
term
針對(duì)term進(jìn)行查詢般哼,如果是 exact_value(keyword)他不會(huì)被分詞,term就是文本本身惠窄,如果是 full_text 文本會(huì)被分詞器分成n多個(gè)term蒸眠,只要其中有任何一個(gè)term在 查詢條件內(nèi)就會(huì)返回。
POST /articles/_search
{
"query": {
"term": {
"content": {
//這里的值一定是分詞后的term值杆融,區(qū)分大小寫
//雖然full_text 里面可能是Spring楞卡,分詞后是spring ,那就應(yīng)該用spring查詢
"value": "spring",
//最終打分結(jié)果會(huì)乘以 boost
"boost": 0
}
}
}
}
Terms Query
只要字段中包括其中一個(gè)term就會(huì)返回脾歇,也允許講其他文檔的字段值作為查詢條件蒋腮。
POST /articles/_search
{
"query": {"terms": {"content": ["spring","cloud"]}}
}
GET /tweets/_search
{
"query" : {
"terms" : {
"user" : {
//使用 index=users type=_doc id=2 path=followers(字段)的值作為terms query查詢
"index" : "users",
"type" : "_doc",
"id" : "2",
"path" : "followers"
}
}
}
}
Terms Set Query
與terms query 一樣,但是可以額外制定必須匹配數(shù)量藕各,這個(gè)數(shù)量可以來源于文檔的字段徽惋,或者通過腳本計(jì)算。
POST /users/_search
{
"query": {
"terms_set":{
"followers":{
"terms":[1,30],
// 這個(gè)表示匹配的數(shù)量必須是字段num的value
# "minimum_should_match_field":"num",
// 這里指明匹配的數(shù)量必須是 terms 數(shù)組的長(zhǎng)度
"minimum_should_match_script": {
// Math.min(params.num_terms, doc['required_matches'].value)
"source": "params.num_terms"
}
}
}
}
}
Range Query
范圍查詢 gt(大于)gte(大于等于)lt(小于)lte(小于等于)
POST /users/_search
{
"query": {
"range": {
"num": {
"gte": 1,
"lte": 20
}
}
}
}
POST /users/_search
{
"query": {
"range": {
"birthday": {
//日期字段可以使用now-1d/d 表示大于當(dāng)前時(shí)間減一天的數(shù)據(jù)
//這部分函數(shù)可以查看 Date Math 相關(guān)文檔
"gt": "now-1d/d"
}
}
}
}
Exists Query
查詢字段不為null 或 [] 的文檔座韵,如果想表達(dá) not exists 就必須用 bool query 包裝
POST /users/_search
{
"query": {
"exists": {
"field": "followers"
}
}
}
POST /users/_search
{
"query": {
"bool": {
"must_not": [
{"exists": {"field": "followers"}}
]
}
}
}
Prefix Query
文本不分詞险绘,進(jìn)行前綴查詢
GET /_search
{ "query": {
"prefix" : { "user" : "ki" }
}
}
Wildcard Query
term 模糊匹配踢京,* 0個(gè)或者多個(gè)字符 ? 表示 任何一個(gè)字符
POST /users/_search
{
"query": {
"wildcard": {
"username.keyword": {
"value": "111 ? 222"
}
}
}
}
Regexp Query
正則表達(dá)式匹配,運(yùn)行速度取決于正則表達(dá)式 .* 都非常慢宦棺,應(yīng)該盡可能使用長(zhǎng)前綴匹配瓣距。
- . 表示任意一個(gè)字符
- 表示前一個(gè)字符出現(xiàn)1次或者多次
- 表示前一個(gè)字符出現(xiàn)0次或者多次
- ? 表示出現(xiàn)0次或者一次
- {1,4} 表示出現(xiàn) 大于等于1次 小于等于 4次 {4}表示出現(xiàn)4次,{2,}表示出現(xiàn)2次以上
- (ab)+ 表示(ab)一組出現(xiàn) 1次或者多次
- | 表示 一個(gè)or 的邏輯 如 aa|bb aa or bb
- [abc] 表示 abc [a-c] 表示 abc [^abc] 表示 非 abc \ 用來表示轉(zhuǎn)義 可以轉(zhuǎn)移 -
- ab~cd 表示 以a 開頭緊接著是b 然后跟個(gè)非c的任何字符代咸,以f結(jié)尾
- <1-100> 表示一個(gè)時(shí)間范圍蹈丸,可以匹配到80
- & 表示前后兩個(gè)正則都需要滿足,aaa.+&.+bbb aaabbb match
- @ 表示跟任何 string 都匹配
POST /users/_search
{
"query": {
"regexp": {
"username.keyword": "111.*"
}
}
}
Fuzzy Query
最大編輯舉例匹配(萊文斯坦距離)
POST /users/_search
{
"query": {
"fuzzy": {
"username.keyword": {
"value": "111 2 2",
//表示最大可以編輯兩次
"fuzziness": 2,
//前面6個(gè)字符必須一樣
"prefix_length": 6,
//呐芥?逻杖??
"max_expansions": 100
}
}
}
}
Type Query
index 下 類型查找思瘟,之后類型被弱化了荸百,所以沒什么用了
POST /users/_search
{
"query": {
"type":{
"value":"_doc"
}
}
}
Ids Query
查詢制定id的文檔
GET /users/_search
{
"query": {
"ids" : {
"type" : "_doc",
"values" : ["1", "4", "100"]
}
}
}
操作的時(shí)候不制定前面的索引,直接使用/_search
將會(huì)搜索所有的索引