摘要:簡(jiǎn)單地說(shuō),倒排索引就是把與對(duì)調(diào)之后的索引,構(gòu)建倒排索引的目的是提升搜索性能。本文將介紹中兩種構(gòu)建倒排索引的方法與。
摘要: 為MongoDB中的數(shù)據(jù)構(gòu)建倒排索引(Inverted Index),然后緩存到內(nèi)存中,可以大幅提升搜索性能。本文將通過(guò)為電影數(shù)據(jù)構(gòu)建演員索引,介紹兩種構(gòu)建倒排索引的方法:MapReduce和Aggregation Pipeline。
GitHub地址:
作者: KiwenLau
日期: 2016-09-11
一. 倒排索引倒排索引(Inverted Index),也稱(chēng)為反向索引,維基百科的定義是這樣的:
是一種索引方法,被用來(lái)存儲(chǔ)在全文搜索下某個(gè)單詞在一個(gè)文檔或者一組文檔中的存儲(chǔ)位置的映射。
這個(gè)定義比較學(xué)術(shù),也就是比較反人類(lèi),忽略...
倒排索引是搜索引擎中的核心數(shù)據(jù)結(jié)構(gòu)。搜索引擎的爬蟲(chóng)獲取的網(wǎng)頁(yè)數(shù)據(jù)可以視為鍵值對(duì),其中,Key是網(wǎng)頁(yè)地址(url),而Value是網(wǎng)頁(yè)內(nèi)容。網(wǎng)頁(yè)的內(nèi)容是由很多關(guān)鍵詞(word)組成的,可以視為關(guān)鍵詞數(shù)組。因此,爬蟲(chóng)獲取的網(wǎng)頁(yè)數(shù)據(jù)可以這樣表示:
但是,用戶(hù)是通過(guò)關(guān)鍵詞進(jìn)行搜索的,直接使用原始數(shù)據(jù)進(jìn)行查詢(xún)的話則需要遍歷所有鍵值對(duì)中的關(guān)鍵詞數(shù)組,效率是非常低的。
因此,用于搜索的數(shù)據(jù)結(jié)構(gòu)應(yīng)該以關(guān)鍵詞(word)為Key,以網(wǎng)頁(yè)地址(url)為Value:
這樣的話,查詢(xún)關(guān)鍵詞word2,立即能夠獲取結(jié)果: [ur1, url2, url3]。
簡(jiǎn)單地說(shuō),倒排索引就是把Key與Value對(duì)調(diào)之后的索引,構(gòu)建倒排索引的目的是提升搜索性能。
二. 測(cè)試數(shù)據(jù)MongoDB是文檔型數(shù)據(jù)庫(kù),其數(shù)據(jù)有三個(gè)層級(jí): 數(shù)據(jù)庫(kù)(database),集合(collection)和文檔(document),分別對(duì)應(yīng)關(guān)系型數(shù)據(jù)庫(kù)中的三個(gè)層級(jí)的: 數(shù)據(jù)庫(kù)(database), 表(table),行(row)。MongDB中每個(gè)的文檔是一個(gè)JSON文件,例如,本文使用的movie集合中的一個(gè)文檔如下所示:
{ "_id" : ObjectId("57d02d60b128567fc130287d"), "movie" : "Pride & Prejudice", "starList" : [ "Keira Knightley", "Matthew Macfadyen" ], "__v" : 0 }
該文檔一共有4個(gè)屬性:
_id: 文檔ID,由MongoDB自動(dòng)生成。
__v: 文檔版本,由MongoDB的NodeJS接口Mongoose自動(dòng)生成。
movie: 電影名稱(chēng)。
starList: 演員列表。
可知,這個(gè)文檔表示電影《傲慢與偏見(jiàn)》,由女神凱拉·奈特莉主演。
忽略_id與__v,movie集合的數(shù)據(jù)如下:
{ "movie": "Pride & Prejudice", "starList": ["Keira Knightley", "Matthew Macfadyen"] }, { "movie": "Begin Again", "starList": ["Keira Knightley", "Mark Ruffalo"] }, { "movie": "The Imitation Game", "starList": ["Keira Knightley", "Benedict Cumberbatch"] }
其中,Key為電影名稱(chēng)(movie),而Value為演員列表(starList)。
這時(shí)查詢(xún)Keira Knightley所主演的電影的NodeJS代碼如下:
Movie.find( { starList: "Keira Knightley" }, { _id: 0, movie: 1 }, function(err, results) { if (err) { console.log(err); process.exit(1); } console.log("search movie success: "); console.log(JSON.stringify(results, null, 4)); process.exit(0); });
注:本文所有代碼使用了MongoDB的NodeJS接口Mongoose,它與MongoDB Shell的接口基本一致。
代碼并不復(fù)雜,但是數(shù)據(jù)量大時(shí)查詢(xún)性能會(huì)很差,因?yàn)檫@個(gè)查詢(xún)需要:
遍歷整個(gè)movie集合的所有文檔
遍歷每個(gè)文檔的startList數(shù)組
構(gòu)建倒排索引可以有效地提升搜索性能。本文將介紹MongoDB中兩種構(gòu)建倒排索引的方法:MapReduce與Aggregation Pipeline。
三 MapReduceMapReduce是由谷歌提出的編程模型,適用于多種大數(shù)據(jù)處理場(chǎng)景,在搜索引擎中,MapReduce可以用于構(gòu)建網(wǎng)頁(yè)數(shù)據(jù)的倒排索引,也可以用于編寫(xiě)網(wǎng)頁(yè)排序算法PageRank(由谷歌創(chuàng)始人佩奇和布林提出)。
MapReduce的輸入數(shù)據(jù)與輸出數(shù)據(jù)均為鍵值對(duì)。MapReduce分為兩個(gè)函數(shù): Map與Reduce。
Map函數(shù)將輸入鍵值
MapReduce框架會(huì)自動(dòng)對(duì)中間鍵值對(duì)
Reduce函數(shù)對(duì)
使用MapReduce構(gòu)建倒排索引的NodeJS代碼如下:
var option = {}; option.map = function() { var movie = this.movie; this.starList.forEach(function(star) { emit(star, { movieList: [movie] }); }); }; option.reduce = function(key, values) { var movieList = []; values.forEach(function(value) { movieList.push(value.movieList[0]); }); return { movieList: movieList }; }; Movie.mapReduce(option, function(err, results) { if (err) { console.log(err); process.exit(1); } console.log("create inverted index success: "); console.log(JSON.stringify(results, null, 4)); process.exit(0); });
代碼解釋:
Map函數(shù)的輸入數(shù)據(jù)是Movie集合中的各個(gè)文檔,在代碼中用this表示。文檔的movie與starList屬性構(gòu)成鍵值對(duì)
MongoDB的MapReduce執(zhí)行框架對(duì)成鍵值對(duì)
Reduce函數(shù)的輸入數(shù)據(jù)是鍵值對(duì)
在代碼中,Map函數(shù)與Reduce返回的鍵值對(duì)中的Value是一個(gè)對(duì)象{ movieList: movieList },而不是數(shù)組movieList,因此代碼和結(jié)果都顯得比較奇怪。MongoDB的MapReduce框架不支持Reduce函數(shù)返回?cái)?shù)組,因此只能將movieList放在對(duì)象里面返回。
輸出結(jié)果:
[ { "_id": "Benedict Cumberbatch", "value": { "movieList": [ "The Imitation Game" ] } }, { "_id": "Keira Knightley", "value": { "movieList": [ "Pride & Prejudice", "Begin Again", "The Imitation Game" ] } }, { "_id": "Mark Ruffalo", "value": { "movieList": [ "Begin Again" ] } }, { "_id": "Matthew Macfadyen", "value": { "movieList": [ "Pride & Prejudice" ] } } ]四. Aggregation Pipeline
Aggregation Pipeline,中文稱(chēng)作聚合管道,用于匯總MongoDB中多個(gè)文檔中的數(shù)據(jù),也可以用于構(gòu)建倒排索引。
Aggregation Pipeline進(jìn)行各種聚合操作,并且可以將多個(gè)聚合操作組合使用,類(lèi)似于Linux中的管道操作,前一個(gè)操作的輸出是下一個(gè)操作的輸入。
使用Aggregation Pipeline構(gòu)建倒排索引的NodeJS代碼如下:
Movie.aggregate([ { "$unwind": "$starList" }, { "$group": { "_id": "$starList", "movieList": { "$push": "$movie" } } }, { "$project": { "_id": 0, "star": "$_id", "movieList": 1 } }], function(err, results) { if (err) { console.log(err); process.exit(1); } console.log("create inverted index success: "); console.log(JSON.stringify(results, null, 4)); process.exit(0); });
代碼解釋:
$unwind: 將starList拆分,輸出結(jié)果(忽略_id與__v)為:
[ { "movie": "Pride & Prejudice", "starList": "Keira Knightley" }, { "movie": "Pride & Prejudice", "starList": "Matthew Macfadyen" }, { "movie": "Begin Again", "starList": "Keira Knightley" }, { "movie": "Begin Again", "starList": "Mark Ruffalo" }, { "movie": "The Imitation Game", "starList": "Keira Knightley" }, { "movie": "The Imitation Game", "starList": "Benedict Cumberbatch" } ]
$group: 根據(jù)文檔的starList屬性進(jìn)行分組,然后將分組文檔的movie屬性合并為movieList,輸出結(jié)果為:
[ { "_id": "Benedict Cumberbatch", "movieList": [ "The Imitation Game" ] }, { "_id": "Matthew Macfadyen", "movieList": [ "Pride & Prejudice" ] }, { "_id": "Mark Ruffalo", "movieList": [ "Begin Again" ] }, { "_id": "Keira Knightley", "movieList": [ "Pride & Prejudice", "Begin Again", "The Imitation Game" ] } ]
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/18882.html
摘要:所有的倒排索引都是基于正排數(shù)據(jù)構(gòu)建的。數(shù)據(jù)規(guī)模的難題節(jié)中描述的拆表的方式,本質(zhì)上是將多個(gè)數(shù)值型拆成了多個(gè)插入記錄,然后再建立倒排索引。 超大規(guī)模檢索中的索引設(shè)計(jì) 一 問(wèn)題背景 1.1 業(yè)務(wù)背景 精準(zhǔn)廣告場(chǎng)景中,人群定向的常用方法是:根據(jù)各種不同的規(guī)則,將每一個(gè)用戶(hù)(User)打上豐富的標(biāo)簽。與此同時(shí),廣告主(Member)在根據(jù)規(guī)則圈選投放人群時(shí),系統(tǒng)也會(huì)將廣告(Ad)打上各種的標(biāo)...
摘要:什么是倒排索引與正排索引相反,由查詢(xún)的過(guò)程,使用倒排索引。分詞后倒排索引我愛(ài)北京到家美好由檢索詞快速找到包含這個(gè)查詢(xún)?cè)~的網(wǎng)頁(yè)就是倒排索引。 △什么是正排索引(forward index)?簡(jiǎn)言之,由key查詢(xún)實(shí)體的過(guò)程,使用正排索引。 例如,用戶(hù)表:t_user(uid, name, passwd, age, sex)由uid查詢(xún)整行的過(guò)程,就時(shí)正排索引查詢(xún)。 又例如,網(wǎng)頁(yè)庫(kù):t_we...
摘要:介紹如何優(yōu)化數(shù)值類(lèi)范圍查詢(xún)。查詢(xún)過(guò)程在中查詢(xún)是基于。在中為了查詢(xún)的這樣一個(gè)條件,會(huì)建立基于的倒排鏈。在單查詢(xún)上可能相比并沒(méi)有明顯優(yōu)勢(shì),甚至?xí)恍K詾榱酥С指咝У臄?shù)值類(lèi)或者多維度查詢(xún),引入類(lèi)。 前言 Lucene 是一個(gè)基于 Java 的全文信息檢索工具包,目前主流的搜索系統(tǒng)Elasticsearch和solr都是基于lucene的索引和搜索能力進(jìn)行。想要理解搜索系統(tǒng)的實(shí)現(xiàn)原理,就...
閱讀 2043·2021-09-07 10:14
閱讀 1478·2019-08-30 15:53
閱讀 2270·2019-08-30 12:43
閱讀 2861·2019-08-29 16:37
閱讀 754·2019-08-26 13:29
閱讀 2000·2019-08-26 13:28
閱讀 437·2019-08-23 18:33
閱讀 3500·2019-08-23 16:09