欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

MongoDB实现基于关键词的文章检索功能(C#版)

程序员文章站 2022-07-06 13:46:58
我的实现目标是: 可以通过一个或多个关键词搜索到文章。 可以通过文章的关键词列表查询到其相关文章。 查询到的结果依据相关程度降序排列。 查询速度要够快。...

我的实现目标是:

可以通过一个或多个关键词搜索到文章。

可以通过文章的关键词列表查询到其相关文章。

查询到的结果依据相关程度降序排列。

查询速度要够快。(理论上关键词检索比全文检索要快很多的)

在网上找了一大圈,就没有一个靠谱的方法,基本都是只能传入单词来检索,而且基本都没有提供c#驱动版本的代码,于是乎自己研究出了这个实现方案:

首先要求使用标签、分词、关键词提取组件对文章对应的关键词进行提取,然后作为数组格式,存入文章的keywords字段中。

MongoDB实现基于关键词的文章检索功能(C#版)

核心检索代码:

/// <summary>
/// 根据关键词获取文章编号与标题映射。
/// 注意:此方法会返回最为匹配的若干个项目,并根据匹配程度降序排列,即使是没有任何关键词匹配项,也会返回若干个结果的。
/// 另需注意:如果是根据文章关键词来查询,一般来说其中一定包含原文章,所以应该把期望获得的数量加1,并在结果中移除原文。
/// </summary>
/// <param name="limitnum">数量上限</param>
/// <param name="keywords">关键词集合</param>
/// <returns>文章编号与标题映射字典</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()方法做查询,find()方法后面跟project()方法也不会改变方法链中操作的对象类型,这样后面的sortbydescending()方法的目标对象还是article类,而不是project()方法中定义的匿名类,而sortbydescending()方法中传入的表达式又仅允许用来选择对象属性,不允许进行任何计算,所以就根本无法实现我们的需求,我在发现aggregate()方法之前就在这里一直卡着很久~

用作关键词搜索时一般就是把关键词传入就可以了,不过传回的结果也有可能压根没有匹配到任何关键词,所以最好在发给用户前再检查一遍项目的匹配程度,把没有任何匹配的结果滤掉。

用作相关文章搜索时,直接把原文章的keywords属性值传入,获取数量要比你预计的数量多1,因为非常可能你的原文章就在获取到的列表中,而且是前列,获取后滤掉原文章的id,再执行take方法返回你需要数量的项目即可(执行take方法是为了以防你的原文没出现在列表中,这概率极小但也是有的)。

为了增进查询效率,还可以预设好索引,代码如下:

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#官方驱动版本是:mongodb.driver.2.2.3