lucene簡(jiǎn)介
??????? lucene是apache頂級(jí)項(xiàng)目,旨在解決企業(yè)中對(duì)于文件的全文檢索問(wèn)題,但是他是一個(gè)解決全文檢索的工具包,提供了完整的查詢引擎和索引引擎,為何說(shuō)他是一個(gè)工具包呢,因?yàn)閷?duì)于全文檢索方案的設(shè)計(jì)還關(guān)乎高并發(fā)實(shí)現(xiàn)即分布式高可用問(wèn)題,極大數(shù)據(jù)存儲(chǔ)問(wèn)題,畢竟對(duì)于大數(shù)據(jù)量來(lái)說(shuō),一個(gè)索引文件遠(yuǎn)遠(yuǎn)不夠,還需要根據(jù)業(yè)務(wù)進(jìn)行路由拆分,如生活搜索類根據(jù)地域拆分索引,電商網(wǎng)站根據(jù)類目拆分索引等,以及索引同步分片問(wèn)題,此類問(wèn)題不在本文敘述中,基于lucene研發(fā)的elasticsearch為開(kāi)發(fā)者和企業(yè)提供了一整套完整解決方案,后文我們將對(duì)elasticsearch進(jìn)行相關(guān)介紹,我們先了解lucene相關(guān)技術(shù)為先。
lucene設(shè)計(jì)策略點(diǎn)簡(jiǎn)述
每個(gè)開(kāi)源軟件設(shè)定總會(huì)有相關(guān)的策略點(diǎn)作為解決方案核心,這是我們閱讀源碼時(shí)需要care的點(diǎn),也是從普通程序員邁向CTO必經(jīng)的轉(zhuǎn)變思考過(guò)程,單純的技術(shù)并不能改變什么,帶有思想的技術(shù)解決方案才是推動(dòng)發(fā)展的靈魂,廢話不多說(shuō),我們先來(lái)闡述前輩們認(rèn)為優(yōu)秀搜索引擎需要具備的特性;
1.面對(duì)海量數(shù)據(jù)快速獲取結(jié)果;
2.查找時(shí)能尋找匹配度最高的文檔;
3.去除無(wú)效語(yǔ)義或者惡意語(yǔ)義對(duì)于文檔結(jié)果的干擾;
4.文檔查找結(jié)果低信息熵;
5.能靈活調(diào)整上述四點(diǎn)屬性;
這里闡述第一點(diǎn),也是很重要的第一點(diǎn),其他三點(diǎn)會(huì)在接下來(lái)的檢索流程講解和索引建立講解中分步描述。
面對(duì)海量數(shù)據(jù)快速獲取相關(guān)結(jié)果
當(dāng)數(shù)據(jù)出現(xiàn)時(shí),檢索的需求就一直隨著計(jì)算機(jī)科學(xué)的發(fā)展一直被不斷地發(fā)展,不管是圖書(shū)館完備的多級(jí)索引作為查找鼻祖,還是后來(lái)針對(duì)業(yè)務(wù)犧牲空間換時(shí)間的宏觀大集群策略,總在找一種折衷且有效的算法去實(shí)現(xiàn)現(xiàn)實(shí)需求,搜索引擎業(yè)界中有一種很經(jīng)典且有效的數(shù)據(jù)結(jié)構(gòu) -- 倒排表
一個(gè)簡(jiǎn)單的比喻來(lái)說(shuō)明倒排表
我們存在一堆散文集,包括魯迅文集,巴金文集,老舍文集等等;存在著不可枚舉的作者、不可枚舉的散文書(shū)、不可枚舉的出版社;按照通常的方法,我們會(huì):
1.將散文集按照作者歸檔;
2.按照作者歸檔的前提下再在作者歸檔集合中按照出版社歸檔;
那么有一天書(shū)店老板來(lái)提貨:我需要魯迅散文集備貨,
針對(duì)此需求你可能會(huì)慶幸,我剛好按照這個(gè)要求將書(shū)進(jìn)行了歸類,OK,一鍋端走;
第二天,又來(lái)了個(gè)書(shū)店老板,我需要機(jī)械出版社的散文集進(jìn)行備貨,你心里就有點(diǎn)犯嘀咕了,差一點(diǎn)翻船,我只要在每個(gè)作者中提取機(jī)械出版社的東西就可以了
第三天,來(lái)了個(gè)很文藝的老板,我需要所有封皮綠色的書(shū),你心里:MMP,挨個(gè)找吧。
這些場(chǎng)景映射進(jìn)入計(jì)算機(jī)中是類似的,你需要建立科學(xué)有效的歸檔字段,否則你就需要逐個(gè)遍歷書(shū)籍,來(lái)提取滿足需求的書(shū)籍,即使有歸檔字段你也需要挨個(gè)查詢歸檔類別,當(dāng)數(shù)據(jù)逐漸擴(kuò)展時(shí),查詢歸檔類別也成了一種負(fù)擔(dān),那么假如建立一種這樣的結(jié)構(gòu),將所有特性提取出來(lái),不通過(guò)任何中間屬性進(jìn)行層級(jí)關(guān)聯(lián),直接關(guān)聯(lián)相關(guān)書(shū)籍,通過(guò)作者、出版社、顏色進(jìn)行提取,并且所有屬性下面直接關(guān)聯(lián)數(shù)據(jù)ID,當(dāng)需求輸入匹配的屬性要求,你就可以直接通過(guò)ID獲取所有相關(guān)的書(shū)籍,跳過(guò)了查找歸類遍歷歸類的步驟,直接獲取數(shù)據(jù)集,形成簡(jiǎn)單高效的查找方式。如下表所示
| 序號(hào) | 書(shū)籍位置 | 書(shū)籍名稱 | 出版社 | 作者 | 顏色 |
|---|---|---|---|---|---|
| 1 | 書(shū)架3層1排第二本 | 朝花夕拾 | 機(jī)械出版社 | 魯迅 | 白色 |
| 2 | 書(shū)架2層2排第三本 | 背影 | 人民出版社 | 朱自清 | 灰色 |
| 3 | 書(shū)架1層4排第一本 | 駱駝祥子 | 機(jī)械出版社 | 魯迅 | 灰色 |
| 4 | 書(shū)架5層2排第五本 | 老舍散文集 | 人民出版社 | 老舍 | 白色 |
那么倒排表的樣子是什么呢?
| 屬性 | 序號(hào) |
|---|---|
| 魯迅 | 1,3 |
| 朱自清 | 2 |
| 老舍 | 4 |
| 機(jī)械出版社 | 1,3 |
| 人民出版社 | 2,4 |
| 白色 | 1,4 |
| 灰色 | 2,3 |
當(dāng)需要機(jī)械出版社書(shū)籍時(shí),找到原始數(shù)據(jù)序號(hào)為1,3的書(shū)籍,就可以直接取貨
需要白色書(shū)籍,找到原始數(shù)據(jù)序號(hào)為1,4的數(shù)據(jù),直接根據(jù)位置取貨
但是有沒(méi)有缺點(diǎn)呢,有,你需要朱姓作者的散文時(shí),倒排表足夠大時(shí),就不能直接查找,只能遍歷倒排表表頭匹配,再查找,違背了設(shè)計(jì)倒排表初衷,所以這是一種以數(shù)據(jù)粒度換取速度的做法,現(xiàn)實(shí)的生產(chǎn)環(huán)境中,只要分詞算法分出來(lái)的倒排表表頭合理,就可以滿足大部分的需求。
lucene評(píng)分機(jī)制簡(jiǎn)析
為何在此優(yōu)先介紹評(píng)分機(jī)制呢?評(píng)分相關(guān)的是檢索時(shí)文檔的排序,而只有清楚需要什么樣的搜索使用策略了,才能去定義如何建立索引策略。
不多說(shuō),看如下的lucene評(píng)分計(jì)算公式

lucene使用的是TF/IDF(term frequency–inverse document frequency)算法,直譯為短語(yǔ)詞頻-反向文檔頻率算法,說(shuō)明主要影響搜索評(píng)分的兩個(gè)宏觀維度為:
1.分詞出來(lái)的詞頻;
2.該詞所出現(xiàn)的文檔數(shù)(即反向文檔頻率);
下面我們來(lái)一一解釋公式每一項(xiàng)所代表的意思。
- coord(q,d) 評(píng)分因子,基于文檔中出現(xiàn)查詢項(xiàng)的個(gè)數(shù)。越多的查詢項(xiàng)在一個(gè)文檔中,說(shuō)明文檔的匹配程度越高。
/*
* @param q 命中短語(yǔ)個(gè)數(shù)
* @param d 查詢短語(yǔ)個(gè)數(shù)
*/
public Float coord(int q,int d) {
return (float)q/(float)d;
}
舉例 this is my blog,查詢?cè)~是Her blog,那么對(duì)應(yīng)的命中短語(yǔ)是 blog 為 1,查詢短語(yǔ)個(gè)數(shù)為 Her blog 為 2,則coord為0.5。
- queryNorm(q)查詢歸一化因子
public float queryNorm(float sumOfSquaredWeights) {
return (float)(1.0 / Math.sqrt(sumOfSquaredWeights));
}
盡管查詢歸一值的目的是為了使查詢結(jié)果之間能夠相互比較,但是它并不十分有效,因?yàn)橄嚓P(guān)度評(píng)分的目的是為了將當(dāng)前查詢的結(jié)果進(jìn)行排序,比較不同查詢結(jié)果的相關(guān)度評(píng)分沒(méi)有太大意義。此公式項(xiàng)對(duì)所有文檔都保持一致,并且不可被更改,所以可以被忽略。
PS:sumOfSquaredWeights 是查詢里每個(gè)詞的 IDF 的平方和。
- tf(t in d) 指項(xiàng)t在文檔d中出現(xiàn)的次數(shù)frequency。具體值為次數(shù)的開(kāi)根號(hào)。
public float tf(float freq) {
return (float)Math.sqrt(freq);
}
如:this blog is my blog.則blog的詞頻為2,tf(2) = √2=1.4142315.
- idf(t) 反轉(zhuǎn)文檔頻率, 出現(xiàn)項(xiàng)t的文檔數(shù)docFreq
public float idf(long docFreq, long numDocs) {
return (float)(Math.log(numDocs/(double)(docFreq+1)) + 1.0);
}
慣例 解釋下這個(gè)公式參數(shù),docFreq:當(dāng)前項(xiàng)匹配的文檔數(shù),numDocs:索引中總文檔數(shù)。
假定索引中有三個(gè)文檔如下
this is a blog.
this is a Technology blog.
this is a website.
搜索詞為blog,則用上述公司換算為In(3/(2+1) + 1) = In(2) = 0.693147181
- t.getBoost 查詢時(shí)候查詢項(xiàng)加權(quán)
為當(dāng)前分詞短語(yǔ)的加權(quán)倍數(shù),默認(rèn)為1,當(dāng)前項(xiàng)<1時(shí)減權(quán)重,當(dāng)前項(xiàng)設(shè)置>1時(shí)增加權(quán)重。
- norm(t,d) 長(zhǎng)度相關(guān)的加權(quán)因子
這個(gè)公式項(xiàng)是一個(gè)匹配度干擾因子,擴(kuò)大長(zhǎng)度對(duì)搜索結(jié)果排序信息熵,舉個(gè)例子:
this is blog;
this is my blog;
blog搜索匹配的時(shí)候,第一句的長(zhǎng)度較短,則計(jì)算出的權(quán)重值較高,換句話說(shuō),對(duì)于搜索短語(yǔ),第一句匹配的比為三分之一,第二句匹配比為四分之一,則代表第一句更匹配搜索短語(yǔ),權(quán)重值需要增大。
小結(jié)
此公式設(shè)置策略總結(jié)為:
1.coord(q,d)強(qiáng)調(diào)搜索短語(yǔ)匹配比,是否被完全匹配,norm(t,d)強(qiáng)調(diào)搜索短語(yǔ)在文檔中匹配命中比,idf(t)計(jì)算文檔中出現(xiàn)搜索短語(yǔ)次數(shù),三項(xiàng)結(jié)合在一起就是擴(kuò)大最終結(jié)果的信息熵,強(qiáng)調(diào)搜索詞在文檔中的匹配度,從命中數(shù),匹配百分比,搜索詞匹配百分比三個(gè)緯度來(lái)影響搜索權(quán)重分值;
2.反向文檔頻率是從搜索整體來(lái)考察搜索短語(yǔ)對(duì)于權(quán)重計(jì)算的輕重,簡(jiǎn)單的道理,物以稀為貴,若這個(gè)短語(yǔ)索引中每個(gè)文檔都有,則認(rèn)為價(jià)值很低,反之,則價(jià)值很高。
3.查詢加權(quán)此項(xiàng)設(shè)立是lucene中甩出的可商業(yè)化定制的項(xiàng),舉個(gè)例子,百度競(jìng)價(jià)排行,解釋完畢~
下文將介紹lucene索引的構(gòu)建過(guò)程和文件格式,想繼續(xù)了解的朋友請(qǐng)耐心等待,我會(huì)一直更新有關(guān)搜索技術(shù)的講解與產(chǎn)品設(shè)計(jì),推薦技術(shù)的講解與產(chǎn)品設(shè)計(jì),作為對(duì)自己前幾年職業(yè)生涯的總結(jié),未完待續(xù),tks~