(六)了解elasticsearch的全文搜索

遇到的問題

通過前面的學(xué)習(xí)响巢,我們已經(jīng)可以使用elasticsearch來進(jìn)行數(shù)據(jù)的搜索了缆八,但此時我們發(fā)現(xiàn)了一個問題吱七,這個問題如果沒有解決好就很影響我們后續(xù)的使用,那么該問題是什么呢指郁?我們來看一下:


搜索“在”關(guān)鍵字.png

上面的截圖是我搜索“在”關(guān)鍵字出來的結(jié)果,按照正常情況下拷呆,我們是不是不應(yīng)該搜索“在”也出來結(jié)果呢闲坎?因?yàn)槲覀冏龅氖撬阉鳎皇悄:樵儾绺热皇撬阉鞯脑捬窍襁@種沒有意義的關(guān)鍵字就不應(yīng)該搜索出來才對的,還有像類似“在”项秉、“是”绣溜、“了”等等這些單獨(dú)存在不能構(gòu)成一個中文詞義的字符也可以搜索了,這顯然是一種搜索效果不好的方式娄蔼。還有一個問題怖喻,我們看看下面的截圖:


搜索“中國人”關(guān)鍵字

上面這個截圖是我搜索“中國人”這個關(guān)鍵詞出來的結(jié)果,然后我們通過高亮匹配的內(nèi)容發(fā)現(xiàn)岁诉,它是“中”锚沸、“國”、“人”拆成3個關(guān)鍵字去匹配內(nèi)容了涕癣,而我們想要的是它匹配“中國人”哗蜈,“中國”,“人”這樣的搜索效果,但現(xiàn)在的情況卻是每個中文字符都能搜索恬叹,這樣就不太智能了候生。
那從表面上看,出現(xiàn)以上兩個問題的原因貌似是因?yàn)閑lasticsearch對中文的分詞不太智能绽昼,它現(xiàn)在的分詞只是簡單的安照每個中文字符來分唯鸭,那如果我們想讓elasticsearch的搜索能更智能一點(diǎn),分析出我們搜索的關(guān)鍵字是否有含義硅确,然后只搜這些有含義的詞語目溉,比如“中國人”,“中國”菱农,“人”缭付,這樣的話我們要做什么操作才能讓elasticsearch支持呢?這個就是我們接下來要探討的問題了循未。
其實(shí)這個問題對elasticsearch來說是很好解決的陷猫,我們只需要換一個分詞算法就可以了,但是為了讓大家對elasticsearch的搜索過程和底層的分詞原理有一個比較深刻的了解的妖,我們不忙著切換其他分詞算法绣檬,而是先來看看全文檢索的一些基礎(chǔ)知識,不然的話大家也僅僅只停留在會用的階段嫂粟,都不知道它底層做了什么事情娇未。

數(shù)據(jù)類型

在詳細(xì)了解全文搜索前,我們先來看看平時我們開發(fā)一個應(yīng)用會遇到什么樣的數(shù)據(jù)星虹,這些數(shù)據(jù)是屬于什么類型的零抬,通過對這些數(shù)據(jù)的了解,我們接下來才能知道全文搜索宽涌,搜索的是什么樣的數(shù)據(jù)平夜。
在開發(fā)過程中通常都會接觸到3種數(shù)據(jù)類型:結(jié)構(gòu)化數(shù)據(jù)、半結(jié)構(gòu)化數(shù)據(jù)和非結(jié)構(gòu)化數(shù)據(jù)卸亮,這3種數(shù)據(jù)有什么特點(diǎn)呢褥芒?
1、結(jié)構(gòu)化數(shù)據(jù):是一種二維結(jié)構(gòu)的數(shù)據(jù)嫡良,也就是說它的數(shù)據(jù)看上去是一個橫向和縱向組成的锰扶,橫向數(shù)據(jù)每一行都代表著一個實(shí)體的信息,縱向的列是固定的寝受,并需要事先確定下來坷牛,是用來描述該實(shí)體的屬性,所以每一行數(shù)據(jù)對應(yīng)的屬性都是一樣的很澄。結(jié)構(gòu)化數(shù)據(jù)可以使用關(guān)系形數(shù)據(jù)庫來儲存京闰,比如我們很熟悉的mysql颜及,oracle等。如下圖所示的數(shù)據(jù):


結(jié)構(gòu)化數(shù)據(jù)

2蹂楣、半結(jié)構(gòu)化數(shù)據(jù):這種數(shù)據(jù)類型其實(shí)也是結(jié)構(gòu)化的數(shù)據(jù)俏站,但是不能使用關(guān)系型數(shù)據(jù)庫來存儲和描述數(shù)據(jù),因?yàn)樗總€實(shí)體的屬性可以不一樣痊土,比如我們描述一個人的實(shí)體信息肄扎,其中一個人可以不描述年齡,一個人可以描述年齡赁酝,而存儲在關(guān)系型數(shù)據(jù)庫中的數(shù)據(jù)每個實(shí)體信息的屬性都是需要一樣的犯祠,但是它的擴(kuò)展性很好,也比純結(jié)構(gòu)化數(shù)據(jù)靈活酌呆。我們經(jīng)常使用的json衡载、xml、yml就是半結(jié)構(gòu)化數(shù)據(jù)隙袁。如下圖所示的數(shù)據(jù):


半結(jié)構(gòu)化數(shù)據(jù)

3痰娱、非結(jié)構(gòu)化數(shù)據(jù):跟結(jié)構(gòu)化數(shù)據(jù)相對應(yīng)的一種數(shù)據(jù),他沒有固定的結(jié)構(gòu)菩收,也就說我們不需要為該數(shù)據(jù)事先定義縱向的屬性列梨睁。比如各種文檔、圖片坛梁、視頻/音頻等而姐。而接下來我們要講的全文搜索腊凶,就是搜索這種非結(jié)構(gòu)化的數(shù)據(jù)划咐。

創(chuàng)建索引過程

通過剛剛我們對數(shù)據(jù)類型的講解,我們知道钧萍,全文搜索是搜索類似文檔這種非結(jié)構(gòu)化數(shù)據(jù)褐缠,并且它們的數(shù)據(jù)量都會比較大,那這樣的話风瘦,如果我們按照傳統(tǒng)的思維來對這些文檔搜索的話队魏,那肯定是搜索的速度會很慢,因?yàn)樗獙@些文檔逐字逐字的掃描万搔,就好比我們看一本書胡桨,如果這本書沒有目錄的話,那么我們要找一個內(nèi)容瞬雹,就要在茫茫字海中尋找昧谊,那這樣的話,我們是否可以把這些內(nèi)容歸納成一個一個章節(jié)酗捌,這些章節(jié)有對應(yīng)的頁碼呢诬,并統(tǒng)一放到一個地方涌哲,我們想要找某個內(nèi)容的時候,先找這個內(nèi)容對應(yīng)的章節(jié)尚镰,再找到該章節(jié)對應(yīng)的頁面阀圾,這樣的話就極大的提高了我們尋找內(nèi)容的速度了,而這些歸納出來的章節(jié)就是我們所說的目錄狗唉。
那別人在做全文搜索的時候初烘,是否也能按照類似書的目錄這種思想來來設(shè)計(jì)呢?答案是肯定的敞曹,但是大家要知道账月,這是一種思想,具體的實(shí)現(xiàn)細(xì)節(jié)有很多澳迫,我們來看看全文搜索的一種很常用的實(shí)現(xiàn)局齿,具體過程如下:

1、給文檔分詞

首先橄登,搜索引擎會有個分詞組件抓歼,我們新建的文檔會傳給分詞組件,然后分詞組件根據(jù)它特定的分詞算法拢锹,把文檔拆分成一個一個的詞元谣妻,如果以elasticsearch默認(rèn)的分詞算法來舉例,那么如果我們創(chuàng)建以下這個文檔:“我是一個中國人卒稳,張姓在中國是大姓蹋半。”充坑,首先傳到分詞組件减江,然后得到以下新的數(shù)據(jù):

我
是
一
個
中
國
人
張
姓
在
中
國
是
大
姓

這些就是分詞組件拿到文檔后拆分出來的詞元集合。

2捻爷、將得到的詞元創(chuàng)建索引

通過分詞組件把文檔拆成詞元后辈灼,搜索引擎會把這些詞元傳給索引組件,索引組件會做以下事情:
(1)利用得到的詞創(chuàng)建一個字典也榄。
索引組件首先會使用剛剛新建文檔得到的詞元放到字典中巡莹,如下圖所示:

字典

該字典會有對應(yīng)的文檔ID

(2)對字典排序
對這些詞進(jìn)行排序,這里的排序算法就以中文拼音首字母順序?yàn)槔?br>

排序.png

(3)合并相同的詞
排好序后甜紫,會合并相同的詞:

合并

Frequency為詞頻率降宅,表示此文檔中包含了幾個此詞。

(4)生成索引文件
最后對排序并合并好的字典生成索引文件囚霸,該索引文件是一個倒排表腰根,鏈表狀的數(shù)據(jù)結(jié)構(gòu),每個詞都會標(biāo)記總共有多少文檔包含此詞邮辽,并且會關(guān)聯(lián)著該詞所在的文檔id唠雕,文檔id又會包含著此文檔中包含了幾個此詞贸营。
Document Frequency 即為文檔頻次,表示總共有多少文檔包含此詞岩睁。

索引文件

如果此時我們再新增一個文檔钞脂,那么該索引文件會發(fā)生什么變化呢?我們來看一下:添加“中國是全球人口最多的國家”捕儒。
此時冰啃,搜索引擎又開始執(zhí)行創(chuàng)建索引的步驟,經(jīng)過1-4的步驟后刘莹,索引文件變成如下這樣:
更新后的索引文件

那么索引引擎在新增一個文檔的時候就要做這些事情了阎毅,最后生成出這些倒排表結(jié)構(gòu)的索引文件,每個詞都會關(guān)聯(lián)著所有包含該詞的文檔id点弯,找到指定的詞扇调,就相當(dāng)于找到該詞對應(yīng)的文檔了。
但是我們通過上述的這些步驟發(fā)現(xiàn)抢肛,添加一個文檔要做的事情還挺多的狼钮,那這樣豈不是降低了我們系統(tǒng)的性能?如果單單從這方面來看捡絮,確實(shí)是熬芜,但是大家要知道,一般來說福稳,我們錄入一個需要做全文索引的數(shù)據(jù)涎拉,一般都是采用異步的方式去給該數(shù)據(jù)創(chuàng)建索引的,也就是說我們會發(fā)一個消息告訴專門創(chuàng)建索引的服務(wù)的圆,并把相關(guān)的數(shù)據(jù)放到消息體鼓拧,整個發(fā)送消息、獲取消息和創(chuàng)建索引的過程都是異步的略板。業(yè)務(wù)系統(tǒng)本身只是發(fā)了個消息毁枯,然后就接著做下面的業(yè)務(wù)慈缔,真正耗性能的創(chuàng)建索引過程由搜索服務(wù)器處理叮称,而搜素服務(wù)器要做集群太簡單了,所以這點(diǎn)性能的消耗并不是什么問題藐鹤。
最重要的是瓤檐,有了這個索引文件,我們要搜索就變得很簡單了娱节,我們不需要在這些文檔中掃描我們要找的內(nèi)容了挠蛉,而是查找索引文件就可以了。那接下來肄满,我們來看看我們在輸入一個關(guān)鍵字后谴古,是如何在索引文件查找內(nèi)容的质涛。

搜索過程

從我們輸入要搜索的關(guān)鍵字到返回搜索結(jié)果這個過程一般要經(jīng)過這幾個步驟:

1、給搜索關(guān)鍵字分詞

首先還是使用分詞組件給搜索關(guān)鍵字分詞掰担,比如用戶輸入“舌尖上的中國”汇陆,那么經(jīng)過分詞組件拆出來的詞就有:

舌
尖
上
的
中
國

2、搜索索引

接著搜索引擎拿著這些拆出來的詞去索引文件找對應(yīng)的詞带饱,由于索引文件是有順序的毡代,一旦找到就停止向下找,然后獲取該詞對應(yīng)的整個文檔鏈表勺疼,如下圖:

搜索結(jié)果

搜索出來的結(jié)果有“的”教寂,“中”,“國”执庐,并且后面帶著該詞所在的文檔id鏈表酪耕。“的”有一個id為2的文檔轨淌,“中”和“國”分別都有id為1和id為2這兩個文檔因妇。但是由于“舌尖上”在索引文件中沒有找到,所以也就沒有搜索結(jié)果了猿诸。

3婚被、鏈表合并

對包含“的”,“中”梳虽,“國”的鏈表進(jìn)行合并操作址芯,得到包含這些詞的所有文檔id,所以最終就得到id為1和2這兩個文檔了窜觉。最后進(jìn)行搜索結(jié)果相關(guān)度排序谷炸,使用特定的相關(guān)度排序算法,根據(jù)詞在文檔出現(xiàn)的頻率和我們提交的排序條件等計(jì)算禀挫,最終把這些文檔id排序旬陡,排序好后默認(rèn)獲取前10條文檔id,如果用戶有提交查詢數(shù)量语婴,那么就獲取用戶提交的數(shù)量描孟,最后通過文檔id查詢出整個文檔返回給用戶。

后記

那么這就是elasticsearch為我們提供搜索服務(wù)時砰左,它要做的事情了匿醒,了解了這些大致的過程有利于我們更好的使用搜索引擎,并擴(kuò)展一些基礎(chǔ)知識缠导。那么現(xiàn)在我們回到最開始說的遇到的問題上廉羔,我們說elasticsearch不夠智能,它只是簡單的按照一個一個字符去搜索文檔的內(nèi)容僻造,導(dǎo)致沒有語義的字符也搜索出結(jié)果了憋他。那這個問題孩饼,我們通過上面的全文搜索過程可以知道,問題是出在分詞這一塊竹挡,也就是說分詞的時候它是一個一個字符串去分的捣辆,最終導(dǎo)致索引文件保存的是文檔中所有詞。
那這個問題如何解決呢此迅?elasticsearch是否提供其他的分詞算法汽畴,讓它支持中文語義來分詞,這樣的話耸序,保存在索引文件中的詞就不再是一個一個的字符忍些,而是有意義的詞語,比如“我是一個中國人坎怪,張姓在中國是大姓罢坝。”這個文檔搅窿,就變成了這樣:

是一個
中國
中國人
人
張姓

那我們下一章就來了解一下elasticsearch的分詞組件嘁酿,看看它給我們提供了哪些分詞組件,和這些分詞組件的特點(diǎn)是怎么樣的男应,從而來確定elasticsearch是否內(nèi)置一個更智能的中文分詞方式闹司。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市沐飘,隨后出現(xiàn)的幾起案子游桩,更是在濱河造成了極大的恐慌,老刑警劉巖耐朴,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件借卧,死亡現(xiàn)場離奇詭異,居然都是意外死亡筛峭,警方通過查閱死者的電腦和手機(jī)铐刘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來影晓,“玉大人镰吵,你說我怎么就攤上這事「┘瑁” “怎么了捡遍?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵锌订,是天一觀的道長竹握。 經(jīng)常有香客問我,道長辆飘,這世上最難降的妖魔是什么啦辐? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任谓传,我火速辦了婚禮,結(jié)果婚禮上芹关,老公的妹妹穿的比我還像新娘续挟。我一直安慰自己,他們只是感情好侥衬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布诗祸。 她就那樣靜靜地躺著,像睡著了一般轴总。 火紅的嫁衣襯著肌膚如雪直颅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天怀樟,我揣著相機(jī)與錄音功偿,去河邊找鬼。 笑死往堡,一個胖子當(dāng)著我的面吹牛械荷,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播虑灰,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼吨瞎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了穆咐?” 一聲冷哼從身側(cè)響起关拒,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎庸娱,沒想到半個月后着绊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡熟尉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年归露,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片斤儿。...
    茶點(diǎn)故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡剧包,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出往果,到底是詐尸還是另有隱情疆液,我是刑警寧澤,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布陕贮,位于F島的核電站堕油,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掉缺,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一卜录、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧眶明,春花似錦艰毒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜀肘,卻和暖如春嗦篱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背幌缝。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工灸促, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人涵卵。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓浴栽,卻偏偏與公主長得像,于是被迫代替她去往敵國和親轿偎。 傳聞我的和親對象是個殘疾皇子典鸡,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評論 2 355

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

  • 作者:羅海鵬,叩丁狼教育高級講師坏晦。原創(chuàng)文章萝玷,轉(zhuǎn)載請注明出處。 遇到的問題 通過前面的學(xué)習(xí)昆婿,我們已經(jīng)可以使用elas...
    叩丁狼教育閱讀 812評論 1 7
  • Solr&ElasticSearch原理及應(yīng)用 一球碉、綜述 搜索 http://baike.baidu.com/it...
    樓外樓V閱讀 7,301評論 1 17
  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,938評論 2 89
  • “今宵酒醒何處,楊柳岸仓蛆,曉風(fēng)殘?jiān)隆薄? 挑個下雨天睁冬,背著愛喝的鐵觀音,懷揣一本書看疙,再次踏上一個人的旅...
    拾荒野人閱讀 226評論 0 0
  • 凌晨豆拨,窗外一片朦朧的漆黑,迷糊中聽見媄兒哼哼唧唧的能庆,打開手機(jī)一看3:05施禾,再看看鎂兒,早已將被子踢開搁胆,圓鼓鼓的肚子...
    媄妞兒閱讀 159評論 0 0