在2年前我并不知道搜索是怎么做的吼渡,感覺搜索特別深?yuàn)W族奢,離我遙不可及蹄咖,例如為
么在搜索框中輸入你想要的概念就可以立馬響應(yīng)到你想要的大致內(nèi)容泽示,但有時(shí)搜索出來
的東西確并不是你你想要的東西纠拔,這時(shí)秉剑,你就應(yīng)該提取你的搜索關(guān)鍵詞,重新設(shè)置稠诲,然
后再次嘗試侦鹏,反復(fù)嘗試...直到找到你想要的內(nèi)容,都是也有一種情況吕粹,你想要的內(nèi)容或
許一直出現(xiàn)不了...
首先我想從elasticsearch開始說起种柑,這個(gè)東西第一次接觸是因?yàn)楣镜臉I(yè)務(wù)拓展,數(shù)
據(jù)量的暴增匹耕,使得mysql數(shù)據(jù)庫的join關(guān)聯(lián)反應(yīng)速度變的非常緩慢聚请,這個(gè)時(shí)候,我們通過
中間件canal來同步數(shù)據(jù)到elasticsearch中稳其,然后在elasticsearch中查詢出我們需要的內(nèi)
容驶赏,這里我說的是查詢,而當(dāng)時(shí)的我對于查詢與搜索的概念是這樣理解的既鞠,查詢好像是
精確匹配煤傍,而搜索呢是模糊匹配,剛開始因?yàn)槭菑膍ysql數(shù)據(jù)庫中遷移過來嘱蛋,因此很多的
業(yè)務(wù)都是精確匹配蚯姆,用到的也僅僅是es中的term,range等語法就夠用了洒敏,至多再加上
wildard模糊匹配就可以(前提是對存儲(chǔ)的數(shù)據(jù)沒有進(jìn)行分詞龄恋,當(dāng)然當(dāng)時(shí)的我對什么是分
詞也是不清楚的,只是將其當(dāng)成是與mysql中的like的用法)凶伙,后來來了一個(gè)需求是這樣
的:es中的存儲(chǔ)的docment中有個(gè)name的field郭毕,例如Lilong,而我要是輸入lilong,那么也
需要出來函荣,剛看不是很簡單么显押,只是將存儲(chǔ)的字段利用一個(gè)函數(shù)將其都轉(zhuǎn)化為全部小寫的子串扳肛,然后再將輸入的字段通過lowcase轉(zhuǎn)化為小寫然后進(jìn)行匹配不就行了,這里注意到需要es本身提供一種函數(shù)轉(zhuǎn)化為小寫的就可以了(當(dāng)時(shí)我覺得應(yīng)該有乘碑,因?yàn)閙ysql有挖息,
我將es當(dāng)成數(shù)據(jù)庫了),查找了一些資料后發(fā)現(xiàn)并沒有找到蝉仇,這個(gè)時(shí)候我就想著旋讹,算
了,直接在數(shù)據(jù)入es的時(shí)候進(jìn)行轉(zhuǎn)化進(jìn)好了(其實(shí)這樣是不行的轿衔,因?yàn)樾枨笳宫F(xiàn)的時(shí)候
需要按照Lilong來展現(xiàn)沉迹,而不是lilong),然后想著多做一個(gè)字段吧(剛開始的認(rèn)知),這
樣就可以解決問題了害驹,但是我非常的排斥用這樣方式解決鞭呕,因?yàn)槲倚枰ㄟ^代碼來維護(hù)2
個(gè)字段的數(shù)據(jù),這樣對于后期的維護(hù)無形中就加大的成本宛官,或許是因?yàn)閳?zhí)著吧葫松,并且我
不想影響功能的正常上線,因此我在周末的時(shí)候翻閱了1天的es官方文檔底洗,終于讓我找到了分析器腋么,當(dāng)時(shí)我的心情是很激動(dòng)的
什么是分析器呢亥揖,分析器是有分詞器,過濾器和字符映射器組成的
- 分詞器:將文本分割成詞項(xiàng)费变,記錄下詞項(xiàng)的位置與長度
- 過濾器:小寫過濾器,ASCII過濾器挚歧,同義詞過來器扛稽,詞干過濾器等
- 字符映射器: 字符預(yù)操作,去html標(biāo)簽等等
我只要定義 "caseSensitive": {
"filter": "lowercase",
"type": "custom",
"tokenizer": "keyword"
}就可以解決問題滑负,
后來又來了需求:存儲(chǔ)的數(shù)據(jù)為李小龍,輸入李龍可以出來矮慕,這樣的話我就開始研究跨度查詢,然后是分詞也就是人們常說的倒排索引的原理凡傅,常見的分詞器,為什么倒排搜索響應(yīng)速度比mysql的響應(yīng)速度快(關(guān)鍵是使用了二分法)肠缔,我也逐漸明白換個(gè)角度思考問題有時(shí)候可以很好的解決問題夏跷,例如哼转,在提升反應(yīng)速度的時(shí)候,要是我們一直在思考如何的實(shí)現(xiàn)一個(gè)好的算法來實(shí)現(xiàn)問題壹蔓,到不如可以想著在存儲(chǔ)數(shù)據(jù)的時(shí)候就開始做文章,怎么算呢佣蓉,我覺得計(jì)算有時(shí)與存儲(chǔ)根本就是分不開的亲雪,你要是想實(shí)現(xiàn)一個(gè)好的算法,那么你就應(yīng)該需要首先將你的數(shù)據(jù)存儲(chǔ)的一個(gè)你想要的地方义辕,或者是你覺得很好的
格式存儲(chǔ),像要是mapreduce要是沒有HDFS的支撐我覺得也是不行的灌砖,這樣的話,算法與數(shù)據(jù)結(jié)構(gòu)其實(shí)也根本就是分不開的基显,要是算法離開了數(shù)據(jù)結(jié)構(gòu),就好像是魚兒離開了水库继,同樣的,光有數(shù)據(jù)結(jié)構(gòu)沒有合適的算法制跟,那么存儲(chǔ)的數(shù)據(jù)將沒法提取酱虎,這個(gè)問題討論偏了雨膨,彎回來再討論一下搜索的事情
上面提到了分詞的一些東西读串,我自認(rèn)為我對es的知識點(diǎn)理解的很多了,對于搜索了解的也可以了排监,從es的一些基本知識點(diǎn)杰捂,到es的集群理論舆床,再到項(xiàng)目中遇到的一些坑(例如要是輸入的子串特別長,將導(dǎo)致es反應(yīng)速度變的非常緩慢谷暮,cpu立刻飆升等等)
然而事實(shí)的情況并不是這樣的盛垦,我了解的只是明確用戶的搜索關(guān)鍵字,然后在一個(gè)大型的數(shù)據(jù)倉庫中進(jìn)行匹配腾夯,然后給用戶返回相似度很高的條目,但是前期的一些用戶意圖之類的東西我并不知道蝶俱,或者這個(gè)才是搜索的核心;舉個(gè)例子:用戶輸入 附近的酒店跷乐;要是你將這哥字段進(jìn)行分詞肥败,去掉停詞的愕提,然后是附近,酒店浅侨,然后在數(shù)據(jù)倉庫中匹配這2個(gè)詞,我覺得匹配出來的效果并不是我想要的鼓黔,正確的結(jié)果應(yīng)該是我需要離我較近的酒店不见,做法應(yīng)該是我在數(shù)據(jù)庫中搜索酒店然后再按照離我的距離進(jìn)行由近到遠(yuǎn)的排序,輸出的結(jié)果才是我想要的稳吮,到了這個(gè)時(shí)候,我研究發(fā)現(xiàn)這些關(guān)于用戶意圖識別的東西盡然是人工智能方面的東西灶似,我非常開心,可能是因?yàn)槿斯ぶ悄鼙容^火的原因吧希痴,不管怎么樣春感,我就是想知道這些東西怎么弄虏缸,或許是好奇吧嫩实,我開始研究人工智能的東西寇钉,剛開始研究時(shí)舶赔,發(fā)現(xiàn)需要很多微積分與數(shù)理統(tǒng)計(jì)方面的知識谦秧,我很開心,我認(rèn)為終于可以用到自己以前學(xué)習(xí)的一些東西了(曾經(jīng)數(shù)學(xué)那可是我的強(qiáng)項(xiàng))