Elasticsearch查詢方式整理之一

結(jié)構(gòu)化搜索

在結(jié)構(gòu)化查詢中,我們得到的結(jié)果 總是 非是即否,要么存于集合之中徙邻,要么存在集合之外。結(jié)構(gòu)化查詢不關(guān)心文件的相關(guān)度或評(píng)分畸裳;它簡(jiǎn)單的對(duì)文檔包括或排除處理缰犁。

這在邏輯上是能說通的,因?yàn)橐粋€(gè)數(shù)字不能比其他數(shù)字 更 適合存于某個(gè)相同范圍怖糊。結(jié)果只能是:存于范圍之中帅容,抑或反之。同樣伍伤,對(duì)于結(jié)構(gòu)化文本來說丰嘉,一個(gè)值要么相等,要么不等嚷缭。沒有 更似 這種概念。

精確值查找

當(dāng)進(jìn)行精確值查找時(shí),我們會(huì)使用過濾器(filters)。過濾器很重要简肴,因?yàn)樗鼈儓?zhí)行速度非嘲俨啵快辫狼,不會(huì)計(jì)算相關(guān)度(直接跳過了整個(gè)評(píng)分階段)而且很容易被緩存。請(qǐng)盡可能多的使用過濾式查詢。

term查詢數(shù)字

一般sql表達(dá)

select document from products where price = 20

對(duì)應(yīng)的term搜索

{
  "term" : {
    "price" : 20
   }
}

通常當(dāng)查找一個(gè)精確值的時(shí)候,我們不希望對(duì)查詢進(jìn)行評(píng)分計(jì)算。只希望對(duì)文檔進(jìn)行包括或排除的計(jì)算修噪,所以我們會(huì)使用 constant_score 查詢以非評(píng)分模式來執(zhí)行 term 查詢并以一作為統(tǒng)一評(píng)分脏款。
最終組合的結(jié)果是一個(gè) constant_score 查詢,它包含一個(gè) term 查詢:

GET /my_store/products/_search
{
    "query" : {
        "constant_score" : { 
            "filter" : {
                "term" : { 
                    "price" : 20
                }
            }
        }
    }
}

1腺占、查詢置于 filter 語句內(nèi)不進(jìn)行評(píng)分或相關(guān)度的計(jì)算积蔚,所以所有的結(jié)果都會(huì)返回一個(gè)默認(rèn)評(píng)分 1
2、我們用 constant_score 將 term 查詢轉(zhuǎn)化成為過濾器

對(duì)于not_analyzed的字段,term查詢不會(huì)對(duì)其進(jìn)行任何分析,比如分詞

組合過濾器

將兩個(gè) term 過濾器置入 bool 過濾器的 should 語句內(nèi),再增加一個(gè)語句處理 NOT 非的條件:

GET /my_store/products/_search
{
   "query" : {
      "filtered" : { 
         "filter" : {
            "bool" : {
              "should" : [
                 { "term" : {"price" : 20}}, 
                 { "term" : {"productID" : "XHDK-A-1293-#fJ3"}} 
              ],
              "must_not" : {
                 "term" : {"price" : 30} 
              }
           }
         }
      }
   }
}

注意泵肄,我們?nèi)匀恍枰粋€(gè) filtered 查詢將所有的東西包起來冯丙。

查找多個(gè)精確值

term 查詢對(duì)于查找單個(gè)值非常有用,但通常我們可能想搜索多個(gè)值。 不需要使用多個(gè) term 查詢,我們只要用單個(gè) terms 查詢(注意末尾的 s ), terms 查詢好比是 term 查詢的復(fù)數(shù)形式(以英語名詞的單復(fù)數(shù)做比)理郑。

它幾乎與 term 的使用方式一模一樣,與指定單個(gè)價(jià)格不同赚爵,我們只要將 term 字段的值改為數(shù)組即可:

{
    "terms" : {
        "price" : [20, 30]
    }
}

范圍

"range" : {
    "price" : {
        "gte" : 20,
        "lte" : 40
    }
}

日期范圍

字符串范圍

按照字典序排列棉胀,但是效率可能比較低下唁奢,最好不用

處理null值

存在查詢

第一件武器就是 exists 存在查詢赐纱,這個(gè)查詢會(huì)返回那些在指定字段有任何值的文檔。

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter" : {
                "exists" : { "field" : "tags" }
            }
        }
    }
}

缺失查詢

這個(gè) missing 查詢本質(zhì)上與 exists 恰好相反:它返回某個(gè)特定 值字段的文檔火俄。

GET /my_index/posts/_search
{
    "query" : {
        "constant_score" : {
            "filter": {
                "missing" : { "field" : "tags" }
            }
        }
    }
}

緩存

Elasticsearch 的較早版本中犯建,默認(rèn)的行為是緩存一切可以緩存的對(duì)象。這也通常意味著系統(tǒng)緩存 bitsets 太富侵略性,從而因?yàn)榍謇砭彺鎺硇阅軌毫ΣN酢2粌H如此否彩,盡管很多過濾器都很容易被評(píng)價(jià),但本質(zhì)上是慢于緩存的(以及從緩存中復(fù)用)嗦随。緩存這些過濾器的意義不大列荔,因?yàn)榭梢院?jiǎn)單地再次執(zhí)行過濾器。

檢查一個(gè)倒排是非趁赌幔快的贴浙,然后絕大多數(shù)查詢組件卻很少使用它。例如 term 過濾字段 "user_id" :如果有上百萬的用戶署恍,每個(gè)具體的用戶 ID 出現(xiàn)的概率都很小崎溃。那么為這個(gè)過濾器緩存 bitsets 就不是很合算,因?yàn)榫彺娴慕Y(jié)果很可能在重用之前就被剔除了盯质。

這種緩存的擾動(dòng)對(duì)性能有著嚴(yán)重的影響袁串。更嚴(yán)重的是,它讓開發(fā)者難以區(qū)分有良好表現(xiàn)的緩存以及無用緩存呼巷。

為了解決問題囱修,Elasticsearch 會(huì)基于使用頻次自動(dòng)緩存查詢。如果一個(gè)非評(píng)分查詢?cè)谧罱?256 次查詢中被使用過(次數(shù)取決于查詢類型)朵逝,那么這個(gè)查詢就會(huì)作為緩存的候選蔚袍。但是,并不是所有的片段都能保證緩存 bitset 配名。只有那些文檔數(shù)量超過 10,000 (或超過總文檔數(shù)量的 3% )才會(huì)緩存 bitset 啤咽。因?yàn)樾〉钠慰梢院芸斓倪M(jìn)行搜索和合并,這里緩存的意義不大渠脉。

一旦緩存了宇整,非評(píng)分計(jì)算的 bitset 會(huì)一直駐留在緩存中直到它被剔除。剔除規(guī)則是基于 LRU 的:一旦緩存滿了芋膘,最近最少使用的過濾器會(huì)被剔除鳞青。

全文搜索

基于詞項(xiàng)于基于全文

基于詞項(xiàng)的查詢

如 term 或 fuzzy 這樣的底層查詢不需要分析階段,它們對(duì)單個(gè)詞項(xiàng)進(jìn)行操作为朋。用 term 查詢?cè)~項(xiàng) Foo 只要在倒排索引中查找 準(zhǔn)確詞項(xiàng) 臂拓,并且用 TF/IDF 算法為每個(gè)包含該詞項(xiàng)的文檔計(jì)算相關(guān)度評(píng)分 _score 。

記住 term 查詢只對(duì)倒排索引的詞項(xiàng)精確匹配习寸,這點(diǎn)很重要胶惰,它不會(huì)對(duì)詞的多樣性進(jìn)行處理(如, foo 或 FOO )霞溪。這里孵滞,無須考慮詞項(xiàng)是如何存入索引的中捆。如果是將 ["Foo","Bar"] 索引存入一個(gè)不分析的( not_analyzed )包含精確值的字段,或者將 Foo Bar 索引到一個(gè)帶有 whitespace 空格分析器的字段坊饶,兩者的結(jié)果都會(huì)是在倒排索引中有 Foo 和 Bar 這兩個(gè)詞

基于全文的查詢

matchquery_string 這樣的查詢是高層查詢泄伪,它們了解字段映射的信息:

  • 如果查詢 日期(date)整數(shù)(integer) 字段,它們會(huì)將查詢字符串分別作為日期或整數(shù)對(duì)待匿级。
  • 如果查詢一個(gè)( not_analyzed )未分析的精確值字符串字段蟋滴,它們會(huì)將整個(gè)查詢字符串作為單個(gè)詞項(xiàng)對(duì)待。
  • 但如果要查詢一個(gè)( analyzed )已分析的全文字段痘绎,它們會(huì)先將查詢字符串傳遞到一個(gè)合適的分析器脓杉,然后生成一個(gè)供查詢的詞項(xiàng)列表。

一旦組成了詞項(xiàng)列表简逮,這個(gè)查詢會(huì)對(duì)每個(gè)詞項(xiàng)逐一執(zhí)行底層的查詢,再將結(jié)果合并尿赚,然后為每個(gè)文檔生成一個(gè)最終的相關(guān)度評(píng)分散庶。

我們很少直接使用基于詞項(xiàng)的搜索,通常情況下都是對(duì)全文進(jìn)行查詢凌净,而非單個(gè)詞項(xiàng)悲龟,這只需要簡(jiǎn)單的執(zhí)行一個(gè)高層全文查詢(進(jìn)而在高層查詢內(nèi)部會(huì)以基于詞項(xiàng)的底層查詢完成搜索)。

匹配查詢

匹配查詢 match 是個(gè) 核心 查詢冰寻。無論需要查詢什么字段须教, match 查詢都應(yīng)該會(huì)是首選的查詢方式。它是一個(gè)高級(jí) 全文查詢 斩芭,這表示它既能處理全文字段轻腺,又能處理精確字段。

這就是說划乖, match 查詢主要的應(yīng)用場(chǎng)景就是進(jìn)行全文搜索

單個(gè)詞查詢

我們用第一個(gè)示例來解釋使用 match 查詢搜索全文字段中的單個(gè)詞:

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}

Elasticsearch 執(zhí)行上面這個(gè) match 查詢的步驟是:

  1. 檢查字段類型 贬养。
    標(biāo)題 title 字段是一個(gè) string 類型( analyzed )已分析的全文字段,這意味著查詢字符串本身也應(yīng)該被分析琴庵。

  2. 分析查詢字符串 误算。
    將查詢的字符串 QUICK! 傳入標(biāo)準(zhǔn)分析器中,輸出的結(jié)果是單個(gè)項(xiàng) quick 迷殿。因?yàn)橹挥幸粋€(gè)單詞項(xiàng)儿礼,所以 match 查詢執(zhí)行的是單個(gè)底層 term 查詢。

  3. 查找匹配文檔 庆寺。
    用 term 查詢?cè)诘古潘饕胁檎?quick 然后獲取一組包含該項(xiàng)的文檔蚊夫,本例的結(jié)果是文檔:1、2 和 3 止邮。

  4. 為每個(gè)文檔評(píng)分 这橙。
    用 term 查詢計(jì)算每個(gè)文檔相關(guān)度評(píng)分 _score 奏窑,這是種將 詞頻(term frequency,即詞 quick 在相關(guān)文檔的 title 字段中出現(xiàn)的頻率)和反向文檔頻率(inverse document frequency屈扎,即詞 quick 在所有文檔的 title 字段中出現(xiàn)的頻率)埃唯,以及字段的長(zhǎng)度(即字段越短相關(guān)度越高)相結(jié)合的計(jì)算方式。

多詞查詢

GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "BROWN DOG!"
        }
    }
}

match 查詢必須查找兩個(gè)詞( ["brown","dog"] )鹰晨,它在內(nèi)部實(shí)際上先執(zhí)行兩次 term 查詢墨叛,然后將兩次查詢的結(jié)果合并作為最終結(jié)果輸出。為了做到這點(diǎn)模蜡,它將兩個(gè) term 查詢包入一個(gè) bool 查詢中漠趁,詳細(xì)信息見 布爾查詢

以上示例告訴我們一個(gè)重要信息:即任何文檔只要 title 字段里包含 指定詞項(xiàng)中的至少一個(gè)詞 就能匹配忍疾,被匹配的詞項(xiàng)越多闯传,文檔就越相關(guān)。

提高精度

任意 查詢?cè)~項(xiàng)匹配文檔可能會(huì)導(dǎo)致結(jié)果中出現(xiàn)不相關(guān)的長(zhǎng)尾卤妒。這是種散彈式搜索甥绿。可能我們只想搜索包含 所有 詞項(xiàng)的文檔则披,也就是說共缕,不去匹配 brown OR dog,而通過匹配 brown AND dog 找到所有文檔士复。

match 查詢還可以接受 operator 操作符作為輸入?yún)?shù)图谷,默認(rèn)情況下該操作符是 or 。我們可以將它修改成 and 讓所有指定詞項(xiàng)都必須匹配阱洪。

控制精度

所有任意 間二選一有點(diǎn)過于非黑即白便贵。 如果用戶給定 5 個(gè)查詢?cè)~項(xiàng),想查找只包含其中 4 個(gè)的文檔冗荸,該如何處理嫉沽?將 operator 操作符參數(shù)設(shè)置成 and 只會(huì)將此文檔排除。

有時(shí)候這正是我們期望的俏竞,但在全文搜索的大多數(shù)應(yīng)用場(chǎng)景下绸硕,我們既想包含那些可能相關(guān)的文檔,同時(shí)又排除那些不太相關(guān)的魂毁。換句話說玻佩,我們想要處于中間某種結(jié)果。

match 查詢支持 minimum_should_match 最小匹配參數(shù)席楚, 這讓我們可以指定必須匹配的詞項(xiàng)數(shù)用來表示一個(gè)文檔是否相關(guān)咬崔。我們可以將其設(shè)置為某個(gè)具體數(shù)字,更常用的做法是將其設(shè)置為一個(gè)百分?jǐn)?shù),因?yàn)槲覀儫o法控制用戶搜索時(shí)輸入的單詞數(shù)量垮斯。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末郎仆,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子兜蠕,更是在濱河造成了極大的恐慌扰肌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件熊杨,死亡現(xiàn)場(chǎng)離奇詭異曙旭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)晶府,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門桂躏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人川陆,你說我怎么就攤上這事剂习。” “怎么了较沪?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵进倍,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我购对,道長(zhǎng),這世上最難降的妖魔是什么陶因? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任骡苞,我火速辦了婚禮,結(jié)果婚禮上楷扬,老公的妹妹穿的比我還像新娘解幽。我一直安慰自己,他們只是感情好烘苹,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布躲株。 她就那樣靜靜地躺著,像睡著了一般镣衡。 火紅的嫁衣襯著肌膚如雪霜定。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天廊鸥,我揣著相機(jī)與錄音望浩,去河邊找鬼。 笑死惰说,一個(gè)胖子當(dāng)著我的面吹牛磨德,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼典挑,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼酥宴!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起您觉,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤拙寡,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后顾犹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體倒庵,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年炫刷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了擎宝。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浑玛,死狀恐怖绍申,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情顾彰,我是刑警寧澤极阅,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站涨享,受9級(jí)特大地震影響筋搏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜厕隧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一奔脐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吁讨,春花似錦髓迎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至翎朱,卻和暖如春橄维,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背拴曲。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工挣郭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疗韵。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓兑障,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子流译,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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