【ES】ElasticSearch 結(jié)構(gòu)化查詢和過(guò)濾

[TOC]

一刷允、DSL

在 ElasticSearch 中,提供了功能十分豐富碧囊、多種表現(xiàn)形式的查詢語(yǔ)言—— DSL 查詢恃锉。

Query DSL 又叫結(jié)構(gòu)化查詢,使用 JSON 格式的請(qǐng)求體 與 ElasticSearch 交互呕臂,使查詢語(yǔ)句更靈活、更精確肪跋、更易讀且易調(diào)試歧蒋。

使用結(jié)構(gòu)化查詢,你需要傳遞 query 參數(shù):

GET /_search
{
    "query": YOUR_QUERY_HERE
}

主要包含兩種類型的查詢語(yǔ)句:葉子查詢語(yǔ)句復(fù)合查詢語(yǔ)句州既。

1.1谜洽、葉子查詢語(yǔ)句

這種查詢可以單獨(dú)使用,針對(duì)指定的字段查詢指定的值吴叶,例如:match, term, range 等阐虚。

一個(gè)葉子查詢語(yǔ)句一般使用這種結(jié)構(gòu):

{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}

或指向一個(gè)指定的字段:

{
    QUERY_NAME: {
        FIELD_NAME: {
            ARGUMENT: VALUE,
            ARGUMENT: VALUE,...
        }
    }
}

例如,可以使用 match 查詢子句用來(lái)找尋在 tweet 字段中找尋包含 elasticsearch 的成員:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}

1.2蚌卤、復(fù)合查詢語(yǔ)句

這種查詢可以合并其他的葉子查詢或復(fù)合查詢实束,從而實(shí)現(xiàn)非常復(fù)雜的查詢邏輯。

例如逊彭,bool 子句允許合并其他的合法子句咸灿,mustmust_not 或者 should

{
    "bool": {
        "must":     { "match": { "tweet": "elasticsearch" }},
        "must_not": { "match": { "name":  "mary" }},
        "should":   { "match": { "tweet": "full text" }}
    }
}

二侮叮、Query DSL 和 Filter DSL

Elasticsearch 使用的查詢語(yǔ)言(DSL) 擁有一套查詢組件避矢,這些組件可以以無(wú)限組合的方式進(jìn)行搭配。這套組件可以在以下兩種情況下使用:查詢情況 query context過(guò)濾情況 filtering context 囊榜,也即結(jié)構(gòu)化查詢 Query DSL結(jié)構(gòu)化過(guò)濾 Filter DSL审胸。

查詢與過(guò)濾語(yǔ)句非常相似扔字,但是它們由于使用目的不同而稍有差異蛉威。

2.1、Query DSL

在上下文查詢語(yǔ)境中卑吭,查詢語(yǔ)句會(huì)詢問(wèn)文檔與查詢語(yǔ)句的匹配程度豆赏,它會(huì)判斷文檔是否匹配并計(jì)算相關(guān)性評(píng)分(_score)的值掷邦。

例如:

  • 查找與 full text search 這個(gè)詞語(yǔ)最佳匹配的文檔
  • 查找包含單詞 run抚岗,但是也包含runs, running, jogsprint的文檔
  • 同時(shí)包含著 quick, brownfox--- 單詞間離得越近宣蔚,該文檔的相關(guān)性越高
  • 標(biāo)識(shí)著 lucene, searchjava--- 標(biāo)識(shí)詞越多胚委,該文檔的相關(guān)性越高

一條查詢語(yǔ)句會(huì)計(jì)算每個(gè)文檔與查詢語(yǔ)句的相關(guān)性亩冬,然后給出一個(gè)相關(guān)性評(píng)分 _score硅急,并且按照相關(guān)性對(duì)匹配到的文檔進(jìn)行排序铜秆。

2.2讶迁、Filter DSL

在上下文過(guò)濾語(yǔ)境中巍糯,查詢語(yǔ)句主要解決文檔是否匹配的問(wèn)題祟峦,而不會(huì)在意匹配程度(相關(guān)性評(píng)分)。

例如:

  • created 的日期范圍是否在 20132014 ?
  • status 字段中是否包含單詞 "published" ?
  • lat_lon 字段中的地理位置與目標(biāo)點(diǎn)相距是否不超過(guò)10km ?

2.3针姿、比較

相關(guān)度:

  • filter —— 只根據(jù)搜索條件過(guò)濾出符合的文檔距淫,將這些文檔的評(píng)分固定為1,忽略 TF/IDF 信息蓬衡,不計(jì)算相關(guān)度分?jǐn)?shù)狰晚;
  • query —— 先查詢符合搜索條件的文檔缴啡, 然后計(jì)算每個(gè)文檔對(duì)于搜索條件的相關(guān)度分?jǐn)?shù)壁晒,再根據(jù)評(píng)分倒序排序秒咐。

性能:

  • filter 性能更好,無(wú)排序 —— 不計(jì)算相關(guān)度分?jǐn)?shù)娘汞,不用根據(jù)相關(guān)度分?jǐn)?shù)進(jìn)行排序夕玩,同時(shí) ES 內(nèi)部還會(huì)緩存(cache)比較常用的 filter 的數(shù)據(jù) (使用bitset <0或1> 來(lái)記錄包含與否)禽作;
  • query性能較差旷偿, 有排序 —— 要計(jì)算相關(guān)度分?jǐn)?shù), 要根據(jù)相關(guān)度分?jǐn)?shù)進(jìn)行排序萍程, 并且沒(méi)有cache功能茫负。

原則上來(lái)說(shuō)忍法,使用查詢語(yǔ)句做全文本搜索或其他需要進(jìn)行相關(guān)性評(píng)分的時(shí)候,剩下的全部用過(guò)濾語(yǔ)句勉失。

在進(jìn)行搜索時(shí)戴质,常常會(huì)在查詢語(yǔ)句中告匠,結(jié)合查詢和過(guò)濾來(lái)達(dá)到查詢目的:

{
    "bool": {
        "must":     { "match": { "title": "how to make millions" }},
        "must_not": { "match": { "tag":   "spam" }},
        "should": [
            { "match": { "tag": "starred" }}
        ],
        "filter": {
          "range": { "date": { "gte": "2014-01-01" }} 
        }
    }
}

三后专、重要的查詢過(guò)濾語(yǔ)句

3.1戚哎、match

match查詢是一個(gè)標(biāo)準(zhǔn)查詢型凳,不管全文本查詢還是精確查詢基本上都要用到它嘱函。

如果使用 match 查詢一個(gè)全文本字段往弓,它會(huì)在真正查詢之前用分析器先分析查詢字符:

{
    "match": {
        "tweet": "About Search"
    }
}

如果用match下指定了一個(gè)確切值函似,在遇到數(shù)字,日期顿天,布爾值或者not_analyzed 的字符串時(shí)露氮,它將搜索給定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}

提示: 做精確匹配搜索時(shí)钟沛,最好用過(guò)濾語(yǔ)句恨统,因?yàn)檫^(guò)濾語(yǔ)句可以緩存數(shù)據(jù)三妈。

3.2畴蒲、multi_match

multi_match查詢?cè)试S做match查詢的基礎(chǔ)上同時(shí)搜索多個(gè)字段:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}

3.3、match_phrase

短語(yǔ)查詢掩宜,精確匹配牺汤。查詢a red會(huì)匹配包含a red短語(yǔ)的檐迟,而不會(huì)進(jìn)行分詞查詢,也不會(huì)查詢出包含a 其他詞 red這樣的文檔溶其。

{
    "query": {
        "match_phrase": {
            "ad": "a red"
        }
    }
}

3.4、match_all

使用match_all 可以查詢到所有文檔每瞒,是沒(méi)有查詢條件下的默認(rèn)語(yǔ)句:

{
    "match_all": {}
}

此查詢常用于合并過(guò)濾條件剿骨。 比如說(shuō)需要檢索所有的郵箱浓利,所有的文檔相關(guān)性都是相同的贷掖,所以得到的_score為1苹威。

3.5牙甫、term

term主要用于精確匹配哪些值,比如數(shù)字泻轰,日期浮声,布爾值或 not_analyzed的字符串(即不進(jìn)行分詞器分析旋奢,文檔中必須包含整個(gè)搜索的詞匯):

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

3.6黄绩、terms

termsterm 有點(diǎn)類似爽丹,但 terms 允許指定多個(gè)匹配條件。 如果某個(gè)字段指定了多個(gè)值真仲,那么文檔需要一起去做匹配,類似于 MySQL 的 in 條件:

{
    "terms": {
        "tag": [ "search", "full_text", "nosql" ]
        }
}

3.7软啼、range

range允許按照指定范圍查找一批數(shù)據(jù):

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}

范圍操作符包含:

  • gt :: 大于
  • gte:: 大于等于
  • lt :: 小于
  • lte:: 小于等于

3.8祸挪、exists

用于查找那些指定字段中有值或無(wú)值的文檔贿条。

指定title字段有值:

{
    "exists":   {
        "field":    "title"
    }
}

指定title字段無(wú)值:

{
    "query": {
        "bool": {
            "must_not": {
                "exists": {
                    "field": "group"
                }
            }
        }
    }
}

注:missing 查詢無(wú)值已經(jīng)被取消。

3.9公黑、bool

bool 可以用來(lái)合并多個(gè)條件查詢結(jié)果的布爾邏輯奠骄,它包含一下操作符:

  • must :: 多個(gè)查詢條件的完全匹配含鳞,相當(dāng)于 and
  • should :: 至少有一個(gè)查詢條件匹配芹务,相當(dāng)于 or
  • must_not :: 多個(gè)查詢條件的相反匹配蝉绷,相當(dāng)于 not,忽略相關(guān)性評(píng)分
  • filter:: 必須匹配枣抱,忽略相關(guān)性評(píng)分
POST /_search
{
    "query": {
        "bool" : {
            "must" : {
              "term" : { "last_name" : "smith" }
            },
            "filter": {
              "term" : { "info.interests" : "musics" }
            },
            "must_not" : {
              "range" : {
                "info.age" : { "gte" : 10, "lte" : 25 }
              }
            },
            "should" : [
              { "term" : { "full_name" : "john" } },
              { "term" : { "full_name" : "smith" } }
            ]
        }
    }
}

提示: 如果bool 查詢下沒(méi)有must子句熔吗,那至少應(yīng)該有一個(gè)should子句。但是 如果有must子句佳晶,那么沒(méi)有should子句也可以進(jìn)行查詢桅狠。

四、驗(yàn)證查詢

查詢語(yǔ)句可以變得非常復(fù)雜轿秧,特別是與不同的分析器和字段映射相結(jié)合后中跌,就會(huì)有些難度。

validate API 可以驗(yàn)證一條查詢語(yǔ)句是否合法菇篡。

GET /gb/tweet/_validate/query
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

請(qǐng)求的返回值說(shuō)明這條語(yǔ)句是非法的:

{
  "valid" :         false,
  "_shards" : {
    "total" :       1,
    "successful" :  1,
    "failed" :      0
  }
}

想知道語(yǔ)句非法的具體錯(cuò)誤信息驱还,需要加上 explain 參數(shù):

GET /gb/tweet/_validate/query?explain 
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

explain 參數(shù)可以提供語(yǔ)句錯(cuò)誤的更多詳情咐容,很顯然鸟雏,這里把 query 語(yǔ)句的 match 與字段名位置弄反了。

五锰悼、參考資料

ES 權(quán)威指南

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子幌绍,更是在濱河造成了極大的恐慌主儡,老刑警劉巖寂汇,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異扒磁,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門负懦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颗品,“玉大人锄蹂,你說(shuō)我怎么就攤上這事朝抖∥暄” “怎么了按傅?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵况芒,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我落君,道長(zhǎng)洒宝,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任扒最,我火速辦了婚禮,結(jié)果婚禮上絮爷,老公的妹妹穿的比我還像新娘胸私。我一直安慰自己鳖谈,他們只是感情好缆娃,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俭厚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪政基。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天窖逗,我揣著相機(jī)與錄音址否,去河邊找鬼。 笑死碎紊,一個(gè)胖子當(dāng)著我的面吹牛佑附,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仗考,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼音同,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了秃嗜?” 一聲冷哼從身側(cè)響起权均,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锅锨,沒(méi)想到半個(gè)月后螺句,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡橡类,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年蛇尚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顾画。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡取劫,死狀恐怖匆笤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谱邪,我是刑警寧澤炮捧,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站惦银,受9級(jí)特大地震影響咆课,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜扯俱,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一书蚪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧迅栅,春花似錦殊校、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至让簿,卻和暖如春敬察,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尔当。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工莲祸, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人居凶。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓虫给,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親侠碧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子抹估,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容