MongoDB實(shí)現(xiàn)基于關(guān)鍵詞的文章檢索功能(C#版)
我的實(shí)現(xiàn)目標(biāo)是:
可以通過一個(gè)或多個(gè)關(guān)鍵詞搜索到文章。
可以通過文章的關(guān)鍵詞列表查詢到其相關(guān)文章。
查詢到的結(jié)果依據(jù)相關(guān)程度降序排列。
查詢速度要夠快。(理論上關(guān)鍵詞檢索比全文檢索要快很多的)
在網(wǎng)上找了一大圈,就沒有一個(gè)靠譜的方法,基本都是只能傳入單詞來檢索,而且基本都沒有提供C#驅(qū)動(dòng)版本的代碼,于是乎自己研究出了這個(gè)實(shí)現(xiàn)方案:
首先要求使用標(biāo)簽、分詞、關(guān)鍵詞提取組件對(duì)文章對(duì)應(yīng)的關(guān)鍵詞進(jìn)行提取,然后作為數(shù)組格式,存入文章的Keywords字段中。
核心檢索代碼:
/// <summary> /// 根據(jù)關(guān)鍵詞獲取文章編號(hào)與標(biāo)題映射。 /// 注意:此方法會(huì)返回最為匹配的若干個(gè)項(xiàng)目,并根據(jù)匹配程度降序排列,即使是沒有任何關(guān)鍵詞匹配項(xiàng),也會(huì)返回若干個(gè)結(jié)果的。 /// 另需注意:如果是根據(jù)文章關(guān)鍵詞來查詢,一般來說其中一定包含原文章,所以應(yīng)該把期望獲得的數(shù)量加1,并在結(jié)果中移除原文。 /// </summary> /// <param name="limitNum">數(shù)量上限</param> /// <param name="keywords">關(guān)鍵詞集合</param> /// <returns>文章編號(hào)與標(biāo)題映射字典</returns> public async Task<Dictionary<Guid, string>> GetArticleDicByKeywordsAsync(int limitNum, IEnumerable<string> keywords) { var list = await Database.GetCollection<Domain.Entity.Article>("Article").Aggregate() .Match(q => !q.IsDeleted && q.Keywords != null) .Project(q => new { q.Id, q.Title, Count = q.Keywords.Count(t => keywords.Contains(t)) }) .SortByDescending(q => q.Count) .Limit(limitNum) .ToListAsync(); return list.ToDictionary(f => f.Id, f => f.Title); }
注意:這里一定要用Aggregate()方法做聚合,而不是常用的Find()方法做查詢,F(xiàn)ind()方法后面跟Project()方法也不會(huì)改變方法鏈中操作的對(duì)象類型,這樣后面的SortByDescending()方法的目標(biāo)對(duì)象還是Article類,而不是Project()方法中定義的匿名類,而SortByDescending()方法中傳入的表達(dá)式又僅允許用來選擇對(duì)象屬性,不允許進(jìn)行任何計(jì)算,所以就根本無法實(shí)現(xiàn)我們的需求,我在發(fā)現(xiàn)Aggregate()方法之前就在這里一直卡著很久~
用作關(guān)鍵詞搜索時(shí)一般就是把關(guān)鍵詞傳入就可以了,不過傳回的結(jié)果也有可能壓根沒有匹配到任何關(guān)鍵詞,所以最好在發(fā)給用戶前再檢查一遍項(xiàng)目的匹配程度,把沒有任何匹配的結(jié)果濾掉。
用作相關(guān)文章搜索時(shí),直接把原文章的Keywords屬性值傳入,獲取數(shù)量要比你預(yù)計(jì)的數(shù)量多1,因?yàn)榉浅?赡苣愕脑恼戮驮讷@取到的列表中,而且是前列,獲取后濾掉原文章的ID,再執(zhí)行Take方法返回你需要數(shù)量的項(xiàng)目即可(執(zhí)行Take方法是為了以防你的原文沒出現(xiàn)在列表中,這概率極小但也是有的)。
為了增進(jìn)查詢效率,還可以預(yù)設(shè)好索引,代碼如下:
var c=Database.GetCollection<Domain.Entity.Article>("Article"); c.Indexes.DropAll(); await c.Indexes.CreateOneAsync( Builders<Domain.Entity.Article>.IndexKeys.Ascending(q => q.Keywords)); //參考自:http://mongodb.github.io/mongo-csharp-driver/2.2/reference/driver/admin/#creating-an-index
所使用的C#官方驅(qū)動(dòng)版本是:MongoDB.Driver.2.2.3
相關(guān)文章
MongoDB 復(fù)制(副本集)學(xué)習(xí)筆記
這篇文章主要介紹了MongoDB 復(fù)制(副本集),結(jié)合實(shí)例形式分析了MongoDB數(shù)據(jù)庫復(fù)制的相關(guān)原理、配置、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2019-10-10MySQL和MongoDB設(shè)計(jì)實(shí)例對(duì)比分析
MySQL是關(guān)系型數(shù)據(jù)庫中的明星,MongoDB是文檔型數(shù)據(jù)庫中的翹楚。2011-07-07關(guān)于單臺(tái)MongoDB實(shí)例開啟Oplog的過程詳解
這篇文章主要給大家介紹了關(guān)于單臺(tái)MongoDB實(shí)例開啟Oplog的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-09-09MongoDB 刪除文檔的方式(刪除一個(gè)、批量刪除)
這篇文章主要介紹了MongoDB 刪除文檔的方式(刪除一個(gè)、批量刪除),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04在 Fedora 上安裝 MongoDB 服務(wù)器的方法教程
Mongo是一個(gè)高性能、開源、無模式的、面向文檔的數(shù)據(jù)庫,它是最受歡迎的 NoSQL 數(shù)據(jù)庫之一。這篇文章主要介紹了在 Fedora 上安裝 MongoDB 服務(wù)器的方法,需要的朋友可以參考下2020-03-03Spring Boot中使用MongoDB數(shù)據(jù)庫的方法
MongoDB是一個(gè)介于關(guān)系數(shù)據(jù)庫和非關(guān)系數(shù)據(jù)庫之間的產(chǎn)品,是非關(guān)系數(shù)據(jù)庫當(dāng)中功能最豐富,最像關(guān)系數(shù)據(jù)庫的。他支持的數(shù)據(jù)結(jié)構(gòu)非常松散,是類似json的bjson格式,因此可以存儲(chǔ)比較復(fù)雜的數(shù)據(jù)類型。Mongo最大的特點(diǎn)是他支持的查詢語言非常強(qiáng)大2018-02-02