Elasticsearch(四) RESTful API之搜索

作者:羅海鵬,叩丁狼教育高級(jí)講師另绩。原創(chuàng)文章儒陨,轉(zhuǎn)載請(qǐng)注明出處花嘶。

前言

? ? ? ?上一節(jié)我們已經(jīng)介紹過了使用RESTful API來操作Elasticsearch了,但是上一節(jié)我們只是學(xué)到了如何新增文檔蹦漠、刪除文檔和通過文檔id獲取文檔椭员,那接下來我們將來學(xué)習(xí)一下使用RESTful API來操作Elasticsearch的文檔搜索。

簡單搜索

首先我們來看看不帶任何搜索條件的最簡單的搜索:
GET /store/employee/_search

{
    "took": 203,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 3,
        "max_score": 1,
        "hits": [
            {
                "_index": "store",
                "_type": "employee",
                "_id": "2",
                "_score": 1,
                "_source": {
                    "name": "李四",
                    "age": 24,
                    "about": "我是一個(gè)作家",
                    "interests": [
                        "看書",
                        "寫作"
                    ]
                }
            },
            {
                "_index": "store",
                "_type": "employee",
                "_id": "1",
                "_score": 1,
                "_source": {
                    "name": "張三",
                    "age": 25,
                    "about": "我是一個(gè)中國人笛园,張姓在中國是大姓隘击,你有神馬意見嗎?",
                    "interests": [
                        "sports",
                        "music"
                    ]
                }
            },
           省略下面的數(shù)據(jù).....
        ]
    }
}

通過上面的這個(gè)RESTful API我們可以發(fā)現(xiàn)研铆,我們查詢的依然是store索引庫和employee文檔類型埋同,但是該API跟我們上一節(jié)查詢的又有不一樣的地方,上一節(jié)內(nèi)容我們給了一個(gè)文檔id棵红,獲取指定的文檔內(nèi)容凶赁,而現(xiàn)在我們沒有給指定的文檔id,取而代之的是用了一個(gè)_search這個(gè)URL后綴逆甜。我們來看看這個(gè)返回結(jié)果中各個(gè)字段分別代表什么意思:
took:是查詢花費(fèi)的時(shí)間虱肄,毫秒單位
time_out:標(biāo)識(shí)查詢是否超時(shí)
_shards:描述了查詢分片的信息,查詢了多少個(gè)分片忆绰、成功的分片數(shù)量、失敗的分片數(shù)量等
hits:搜索的結(jié)果可岂,total是全部的滿足的文檔數(shù)目错敢,hits是返回的實(shí)際數(shù)目(默認(rèn)是10)
_score是文檔的分?jǐn)?shù)信息,與排名相關(guān)度有關(guān)缕粹,參考各大搜索引擎的搜索結(jié)果稚茅,就容易理解。

帶搜索條件的搜索
GET /store/employee/_search?q=name:張三

{
    "took": 292,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.5753642,
        "hits": [
            {
                "_index": "store",
                "_type": "employee",
                "_id": "1",
                "_score": 0.5753642,
                "_source": {
                    "name": "張三",
                    "age": 25,
                    "about": "我是一個(gè)中國人平斩,張姓在中國是大姓亚享,你有神馬意見嗎?",
                    "interests": [
                        "sports",
                        "music"
                    ]
                }
            }
        ]
    }
}

通過以上的RESTful API我們可以發(fā)現(xiàn):我們這次使用的RESTful API還是上面那個(gè)URL绘面,但是我們給這個(gè)URL路徑傳入了參數(shù)了欺税,這個(gè)參數(shù)名叫q,參數(shù)的值為name:張三,這就表示我們這次的搜索是需要指定特定內(nèi)容的文檔的揭璃,而這個(gè)特定內(nèi)容就是name這個(gè)字段晚凿,值為張三的文檔。

使用DSL語句搜索

我們除了可以使用簡單的傳參方式搜索外瘦馍,還可以使用Elasticsearch提供豐富且靈活的查詢語言:DSL(Domain Specific Language特定領(lǐng)域語言)查詢,它允許你構(gòu)建更加復(fù)雜歼秽、強(qiáng)大的查詢。DSL以JSON數(shù)據(jù)格式為載體情组,用HTTP請(qǐng)求體傳輸數(shù)據(jù)內(nèi)容燥筷。
match查詢:
POST /store/employee/_search
{ "query" : { "match" : { "name" : "張" } } }

{
    "took": 8,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.2876821,
        "hits": [
            {
                "_index": "store",
                "_type": "employee",
                "_id": "1",
                "_score": 0.2876821,
                "_source": {
                    "name": "張三",
                    "age": 25,
                    "about": "我是一個(gè)中國人箩祥,張姓在中國是大姓,你有神馬意見嗎肆氓?",
                    "interests": [
                        "sports",
                        "music"
                    ]
                }
            }
        ]
    }
}

以上的這種搜索方式跟我們之前使用簡單搜索效果是一樣的袍祖,{ "query" : { "match" : { "name" : "張" } } }這個(gè)JSON數(shù)據(jù)就是Elasticsearch的DSL查詢語言,它需要放到HTTP請(qǐng)求體中做院,query代表執(zhí)行搜索操作盲泛,在該屬性下,可以靈活的使用各種查詢類型進(jìn)行組合键耕,match代表DSL語句中的其中一種查詢類型寺滚,在該屬性中就可以匹配我們需要查詢文檔的什么字段和字段值了,并且可以匹配多個(gè)字段屈雄。
同時(shí)我們根據(jù)返回內(nèi)容上看發(fā)現(xiàn)村视,搜索出的文檔score(得分)為0.28..,這是因?yàn)槲覀冞@次的搜索沒有精準(zhǔn)的匹配name字段為“張三”的文檔酒奶,而是只匹配“張”蚁孔,那么搜索出的文檔得分就比較低了。
除此之外惋嚎,我們還可以結(jié)合DSL語句的其他語法來控制搜索結(jié)果杠氢。如:
{ "query" : { "match_all":{} }, "size":2 }
搜索全部員工文檔,并返回前面兩條數(shù)據(jù)另伍,如果不給size字段鼻百,那么就返回前10條

{ "query" : { "match" : { "name" : "張" } }, "from":2, "size":2 }
搜索name字段帶有“張”的員工文檔摆尝,并且返回搜索結(jié)果從第二條開始温艇,共兩條數(shù)據(jù)

{ "query" : { "match_all":{} }, "sort":{ "age":{"order":"desc"} } }
搜索全部文檔堕汞,并且返回結(jié)果安照“age”字段做倒序排序勺爱。

{ "query":{ "match_phrase":{ "about":"rock climbing" } } }
使用match的話我們只能匹配到一個(gè)單詞,但是如果我們想要同時(shí)匹配多個(gè)單詞的話就不能使用match了讯检,而是使用match_phrase琐鲁,該屬性意思是短語搜索,例如上面這條DSL語句就是搜索包含rock climbing這個(gè)短語的文檔人灼,這個(gè)短語包含兩個(gè)單詞绣否,這個(gè)兩個(gè)單詞是需要相鄰的

bool查詢:
elasticsearch還提供了bool語法查詢挡毅,該語法可以把多個(gè)查詢條件組合在一起蒜撮,看以下的例子:
POST /store/employee/_search
{ "query": { "bool": { "must": [ { "match": { "name": "張" } }, { "range": { "age": { "gte":25 } } } ] } } }
查詢結(jié)果如下:

{
    "took": 18,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 1.5753641,
        "hits": [
            {
                "_index": "store",
                "_type": "employee",
                "_id": "1",
                "_score": 1.5753641,
                "_source": {
                    "name": "張三",
                    "age": 25,
                    "about": "我是一個(gè)中國人,張姓在中國是大姓,你有神馬意見嗎段磨?",
                    "interests": [
                        "sports",
                        "music"
                    ]
                }
            }
        ]
    }
}

以上的查詢涉及到DSL新的語法:bool查詢取逾,這是一個(gè)可以讓我們把多個(gè)搜索條件組合在一起的語法,結(jié)合屬性must意思為所有組合條件都必須滿足苹支。同時(shí)這里還涉及到兩個(gè)新的屬性:range意思為范圍查詢和gte屬性砾隅,意思為大于等于(gt為大于)。
那么整個(gè)查詢語句意思為查詢名字帶有“張”债蜜,并且年齡大于等于25歲的員工文檔晴埂。
此外,bool查詢語法除了must之外寻定,還有must_notshould儒洛。
如果我們把上面那條查詢語句中的must改成should,那么意思就變成了:查詢名字帶有“張”狼速,或者年齡大于等于25歲的員工文檔琅锻。
在一條bool查詢語句中還可以把mustmust_notshould組合成更復(fù)雜的查詢語句向胡,比如以下的這條語句:
{ "query": { "bool": { "must": [ { "match": { "name": "張" } }, { "range": { "age": { "gte":25 } } } ], "must_not":{ "match":{ "age":29 } } } } }
該語句意思是查詢名字包含“張”并且年齡大于等于25歲的恼蓬,但是不包含年齡為29歲的員工文檔。
由此可以看出僵芹,bool查詢可以很靈活的組合各種查詢條件处硬,類似于我們SQL語句中的where多個(gè)條件組合。

過濾查詢
之前我們說過score字段指定了文檔的分?jǐn)?shù)拇派,使用query搜索會(huì)計(jì)算文檔的分?jǐn)?shù)荷辕,最后通過分?jǐn)?shù)確定哪些文檔更相關(guān),返回哪些文檔攀痊,并且文檔的排序默認(rèn)是按分?jǐn)?shù)倒序的桐腌。但是有的時(shí)候我們可能對(duì)分?jǐn)?shù)不感興趣拄显,就可以使用filter進(jìn)行過濾鲫售,它不會(huì)去計(jì)算分值用狱,因此效率也就更高一些。我們來看看以下這條查詢語句:
POST /store/employee/_search
{ "query": { "bool": { "must": { "match_all": {} }, "filter": { "range": { "age": { "gt": 20, "lt": 25 } } } } } }

{
    "took": 44,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 2,
        "max_score": 1,
        "hits": [
            {
                "_index": "store",
                "_type": "employee",
                "_id": "2",
                "_score": 1,
                "_source": {
                    "name": "李四",
                    "age": 24,
                    "about": "I love to go rock climbing",
                    "interests": [
                        "sports",
                        "music",
                        "coding"
                    ]
                }
            },
            {
                "_index": "store",
                "_type": "employee",
                "_id": "1",
                "_score": 1,
                "_source": {
                    "name": "張三",
                    "age": 25,
                    "about": "我是一個(gè)中國人,張姓在中國是大姓概漱,你有神馬意見嗎?",
                    "interests": [
                        "sports",
                        "music"
                    ]
                }
            }
        ]
    }
}

filter過濾可以嵌套在bool查詢內(nèi)部使用掖蛤,比如這條語句意思就是過濾查詢年齡大于20毡鉴,小于25之間的員工文檔。

高亮結(jié)果
所有帶有全文檢索的應(yīng)用在搜索出來的文檔結(jié)果上都會(huì)把搜索詞高亮標(biāo)記博助,這樣用戶就可以直觀的知道為什么這些文檔和查詢條件相匹配了险污。在Elasticsearch中高亮片段是非常容易的,我們可以來看看以下這個(gè)例子:
GET /store/employee/_search
{ "query" : { "match" : { "name" : "張" } }, "highlight": { "fields" : { "name" : {} } } }

{
    "took": 8,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 1,
        "max_score": 0.2876821,
        "hits": [
            {
                "_index": "store",
                "_type": "employee",
                "_id": "1",
                "_score": 0.2876821,
                "_source": {
                    "name": "張三",
                    "age": 25,
                    "about": "我是一個(gè)中國人,張姓在中國是大姓蛔糯,你有神馬意見嗎拯腮?",
                    "interests": [
                        "sports",
                        "music"
                    ]
                },
                "highlight": {
                    "name": [
                        "<em>張</em>三"
                    ]
                }
            }
        ]
    }
}

這樣,我們就可以把搜索名字帶有“張”的員工文檔搜索出來蚁飒,并且搜索的結(jié)果多出了一個(gè)highlight的屬性动壤,在該屬性中有name這個(gè)文檔字段,其中字段值中的“張”是被<em>標(biāo)簽包裹的淮逻,代表高亮的意思琼懊,因?yàn)槲覀兊乃阉髟~就是“張”,所以elasticsearch把結(jié)果中的“張”高亮了爬早。

以上就是常用的搜索語句用法哼丈,當(dāng)然,DSL功能非常強(qiáng)大凸椿,語法也不僅僅只有這些削祈,但是目前為止,我們先學(xué)會(huì)了這些已經(jīng)足夠我們使用了脑漫,后續(xù)章節(jié)如何會(huì)涉及到其他的DSL語句我們?cè)僦鹨坏脑敿?xì)介紹其用法髓抑。

WechatIMG9.jpeg
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市优幸,隨后出現(xiàn)的幾起案子吨拍,更是在濱河造成了極大的恐慌,老刑警劉巖网杆,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羹饰,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡碳却,警方通過查閱死者的電腦和手機(jī)队秩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昼浦,“玉大人馍资,你說我怎么就攤上這事」卦耄” “怎么了鸟蟹?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長使兔。 經(jīng)常有香客問我建钥,道長,這世上最難降的妖魔是什么虐沥? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任熊经,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘镐依。我一直安慰自己悉盆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布馋吗。 她就那樣靜靜地躺著焕盟,像睡著了一般。 火紅的嫁衣襯著肌膚如雪宏粤。 梳的紋絲不亂的頭發(fā)上脚翘,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音绍哎,去河邊找鬼来农。 笑死,一個(gè)胖子當(dāng)著我的面吹牛崇堰,可吹牛的內(nèi)容都是我干的沃于。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼海诲,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼繁莹!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起特幔,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤咨演,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后蚯斯,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體薄风,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年拍嵌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了遭赂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡横辆,死狀恐怖撇他,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情龄糊,我是刑警寧澤逆粹,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布募疮,位于F島的核電站炫惩,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏阿浓。R本人自食惡果不足惜他嚷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧筋蓖,春花似錦卸耘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瓮下,卻和暖如春翰铡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背讽坏。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國打工锭魔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人路呜。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓迷捧,卻偏偏與公主長得像,于是被迫代替她去往敵國和親胀葱。 傳聞我的和親對(duì)象是個(gè)殘疾皇子漠秋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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

  • 博客原文一博客原文二 翻譯作品,水平有限抵屿,如有錯(cuò)誤膛堤,煩請(qǐng)留言指正。原文請(qǐng)見 官網(wǎng)英文文檔 起步 Elasticse...
    rabbitGYK閱讀 3,228評(píng)論 0 68
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理晌该,服務(wù)發(fā)現(xiàn)肥荔,斷路器,智...
    卡卡羅2017閱讀 134,599評(píng)論 18 139
  • 繪本故事《阿文的小毯子》朝群,故事講述的是關(guān)于一只叫做阿文的小老鼠的燕耿,他有個(gè)怪習(xí)慣,(戀物癖)無論是走路姜胖、吃飯誉帅、睡覺還...
    云淡風(fēng)輕紅燕閱讀 273評(píng)論 0 1
  • 轉(zhuǎn)載:http://www.51testing.com/html/68/n-3725668.html? ? 前...
    測(cè)試大頭兵閱讀 953評(píng)論 1 2
  • 本地全局安裝nodenpm install vue-cli -g 安裝vue腳手架vue init webpack...
    閆浩奇閱讀 285評(píng)論 0 2