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

注:此文檔僅適用于 Elasticsearch > 5.0 版本

Elasticsearch 的功能之一就是搜索闻牡,搜索主要分為兩種類型,結(jié)構(gòu)化搜索和全文搜索绳矩。結(jié)構(gòu)化搜索是指有關(guān)探詢那些具有內(nèi)在結(jié)構(gòu)數(shù)據(jù)的過(guò)程罩润。比如日期、時(shí)間和數(shù)字都是結(jié)構(gòu)化的:它們有精確的格式翼馆,我們可以對(duì)這些格式進(jìn)行邏輯操作割以。比較常見(jiàn)的操作包括比較數(shù)字或時(shí)間的范圍,或判定兩個(gè)值的大小写妥。

結(jié)構(gòu)化搜索的特征是『非是即否』拳球,一個(gè)文檔要么存于集合之中,要么存在集合之外珍特。

EndPoints

經(jīng)常的情況下祝峻,需要在一個(gè)或多個(gè)特殊的索引并且在一個(gè)或者多個(gè)特殊的類型中進(jìn)行搜索。我們可以通過(guò)在URL中指定特殊的索引和類型達(dá)到這種效果扎筒,如下所示:

/_search :在所有的索引中搜索所有的類型

/gb/_search :在 gb 索引中搜索所有的類型

/gb,us/_search :在 gbus 索引中搜索所有的文檔

/g*,u*/_search :在任何以 g 或者 u 開(kāi)頭的索引中搜索所有的類型

/gb/user/_search :在 gb 索引中搜索 user 類型

/gb,us/user,tweet/_search :在 gbus 索引中搜索 usertweet 類型

/_all/user,tweet/_search :在所有的索引中搜索 usertweet 類型

精確值查詢

在 Elasticsearch 中莱找,過(guò)濾器不能夠單獨(dú)使用,它必須和 query 一起使用嗜桌,例如下面的查詢例子奥溺。其中 constant_score 表示查詢以非評(píng)分模式進(jìn)行,這樣可以省掉評(píng)分過(guò)程骨宠,提高查詢速度浮定。

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

如果需要查找 object 里面的字段相满,可以使用點(diǎn)語(yǔ)法,例如:

{
    "query" : {
        "constant_score" : { 
            "filter" : { "term" : { "user.id" : 1 } }
        }
    }
}

常用的過(guò)濾器包含 term 桦卒、 terms 立美、 rangeprefix 方灾、 wildcard 建蹄、 regexpexists 裕偿、 missing洞慎。下面進(jìn)行一一介紹。

term

term 代表完全匹配嘿棘,也就是精確查詢劲腿。

注:查詢字符串時(shí),查詢的字段類型必須是 keyword 蔫巩,如果查詢的是 text谆棱, 則有可能查詢結(jié)果不正確。

{
    "query" : {
        "constant_score" : { 
            "filter" : {"term" : { "price" : 20 } }
        }
    }
}

terms

terms 查詢類似于 SQL 中的 in 關(guān)鍵詞圆仔。例如:

{
    "query": {
        "constant_score" : {
            "filter" : {"terms" : { "user" : ["kimchy", "elasticsearch"]}}
        }
    }
}

range

range 主要用于數(shù)字和日期類型的字段查詢垃瞧。例如查詢年齡在 1020 歲的用戶:

{
    "query": {
        "constant_score" : {
            "filter" : {"range" : { "age" : { "gte" : 10, "lte" : 20 } } }
        }
    }
}

range 接受以下幾個(gè)參數(shù):

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

當(dāng)查詢字段的類型是日期時(shí),可以添加 format 類型的字段坪郭,如果時(shí)間字段與時(shí)區(qū)相關(guān)个从,則還可以添加 time_zone 字段。

{
    "query": {
        "constant_score" : {
            "filter" : {
                "range" : { 
                    "age" : { 
                        "gte" : "2015-01-01 00:00:00", 
                        "lte" : "2015-02-01 00:00:00",
                        "format": "yyyy-MM-dd HH:mm:ss", 
                        "time_zone": "+01:00" 
                    } 
                } 
            }
        }
    }
}

prefix

prefix 又稱前綴查詢歪沃,用于 keyword 類型的字段查詢嗦锐。

{
    "query" : {
        "constant_score" : {
            "filter" : {
                "prefix" : { "name" : "ki" }
            }
        }
    }
}

wildcard

wildcard 又稱通配符查詢,也是用于 keyword 類型的字段查詢沪曙。通配符查詢主要基于 shell 的通配符: ? 匹配任意字符奕污, * 匹配 0 或多個(gè)字符。

{
    "query" : {
        "constant_score" : {
            "filter" : {
                "wildcard" : { "name" : "ki*y" }
            }
        }
    }
}

regexp

regexp 又稱正則查詢液走,也是用于 keyword 類型的字段查詢碳默。

{
    "query" : {
        "constant_score" : {
            "filter" : {
                "regexp" : { "name" : "s.*y" }
            }
        }
    }
}

exists 和 missing

exists 字段類似于 SQL 中的 IS NOT NULL ,用于過(guò)濾指定字段不為 NULL 的文檔缘眶。

{
    "query" : {
        "constant_score" : {
            "filter" : {
                "exists" : { "field" : "tags" }
            }
        }
    }
}

missingexists 正相反嘱根,它返回指定字段為 NULL 的文檔。

bool 過(guò)濾器

bool 過(guò)濾器是一個(gè)復(fù)合過(guò)濾器(Compound filter)巷懈,它可以接受多個(gè)其他過(guò)濾器作為參數(shù)该抒,并將這些過(guò)濾器結(jié)合成各式各樣的布爾(邏輯)組合。

一個(gè) bool 過(guò)濾器由三部分組成:

{
   "bool" : {
      "must" :     [],
      "should" :   [],
      "must_not" : [],
      "filter": []
   }
}
  • must: 所有的語(yǔ)句都 必須(must) 匹配顶燕,與 AND 等價(jià)凑保。
  • must_not:所有的語(yǔ)句都 不能(must not) 匹配冈爹,與 NOT 等價(jià)。
  • should:至少有一個(gè)語(yǔ)句要匹配愉适,與 OR 等價(jià)犯助。
  • filter:表示這是一個(gè)過(guò)濾器,與 must 等價(jià)维咸。

filter 的結(jié)果會(huì)緩存,因此盡量使用 filter 關(guān)鍵詞惠爽。

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

上面的查詢等同于 (price = 20 OR productID='XHDK-A-1293-#fJ3') AND price != 30癌蓖。

nested 查詢

nested 類型的字段,由于索引在獨(dú)立的文檔中婚肆,我們無(wú)法通過(guò)點(diǎn)語(yǔ)法直接搜索他們租副。因此 Elasticsearch 開(kāi)發(fā)了 nested 查詢,這個(gè)查詢主要用于查詢 nested 類型字段中的對(duì)象的字段较性。

{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "filter": {
            {"term": {"comments.name": "john"}}
          }
        }
      }
    }
  }
}

排序和分頁(yè)

默認(rèn)情況下用僧,查詢返回的結(jié)果會(huì)按照 _score 進(jìn)行排序,值越高越靠前赞咙。咱結(jié)構(gòu)化搜索中责循,_score 的只都是相等的,因此結(jié)果會(huì)按照隨機(jī)順序返回攀操。

Elasticsearch 提供了結(jié)果排序的功能院仿,可以使用 sort 字段指定排序的方式。

{
    "query" : {
        "bool" : {
            "filter" : { "term" : { "user_id" : 1 }}
        }
    },
    "sort": { "date": { "order": "desc" }}
}

也可以指定多個(gè)字段進(jìn)行排序:

{
    "query" : {
        "bool" : {
            "filter" : { "term" : { "user_id" : 1 }}
        }
    },
    "sort": [
        { "date":   { "order": "desc" }},
        { "name": { "order": "esc" }}
    ]
}

有了排序功能速和,就需要分頁(yè)歹垫。分頁(yè)有 sizefrom 兩個(gè)參數(shù)指定。

  • size :返回的結(jié)果數(shù)量颠放,默認(rèn)10
  • from :跳過(guò)開(kāi)始的結(jié)果數(shù)排惨,默認(rèn)0

下面的例子表示請(qǐng)求第三頁(yè)的數(shù)據(jù)。

{
    "query" : {
        "bool" : {
            "filter" : { "term" : { "user_id" : 1 }}
        }
    },
    "sort": { "date":   { "order": "desc" }},
    "size": 10,
    "from": 20
}

在 Elasticsearch 中碰凶,返回的結(jié)果隨著分頁(yè)的增長(zhǎng)而成倍增長(zhǎng)暮芭。

現(xiàn)在假設(shè)我們請(qǐng)求第1000頁(yè)——結(jié)果10001到10010。工作方式都相同痒留,不同的是每個(gè)分片都必須產(chǎn)生頂端的10010個(gè)結(jié)果谴麦。然后請(qǐng)求節(jié)點(diǎn)排序這50050個(gè)結(jié)果并丟棄50040個(gè)!

因此盡量避免使用深度分頁(yè)伸头。如果有大量分頁(yè)的需求匾效,可以使用 Scrolling 的方式。


參考資料:

  1. Elasticsearch: 權(quán)威指南
  2. Elasticsearch 官方文檔
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末恤磷,一起剝皮案震驚了整個(gè)濱河市面哼,隨后出現(xiàn)的幾起案子野宜,更是在濱河造成了極大的恐慌,老刑警劉巖魔策,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匈子,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡闯袒,警方通過(guò)查閱死者的電腦和手機(jī)虎敦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)政敢,“玉大人其徙,你說(shuō)我怎么就攤上這事∨缁В” “怎么了唾那?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)褪尝。 經(jīng)常有香客問(wèn)我闹获,道長(zhǎng),這世上最難降的妖魔是什么河哑? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任避诽,我火速辦了婚禮,結(jié)果婚禮上灾馒,老公的妹妹穿的比我還像新娘茎用。我一直安慰自己,他們只是感情好睬罗,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布轨功。 她就那樣靜靜地躺著,像睡著了一般容达。 火紅的嫁衣襯著肌膚如雪古涧。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,007評(píng)論 1 284
  • 那天花盐,我揣著相機(jī)與錄音羡滑,去河邊找鬼。 笑死算芯,一個(gè)胖子當(dāng)著我的面吹牛柒昏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播熙揍,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼职祷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起有梆,我...
    開(kāi)封第一講書(shū)人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤是尖,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后泥耀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體饺汹,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年痰催,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了兜辞。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡夸溶,死狀恐怖弦疮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蜘醋,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布咏尝,位于F島的核電站压语,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏编检。R本人自食惡果不足惜胎食,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望允懂。 院中可真熱鬧厕怜,春花似錦、人聲如沸蕾总。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)生百。三九已至递雀,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚀浆,已是汗流浹背缀程。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留市俊,地道東北人杨凑。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像摆昧,于是被迫代替她去往敵國(guó)和親撩满。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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