基于JieBaNet+Lucene.Net实现全文搜索

网友投稿 457 2022-06-21


实现效果:

上一篇文章有附全文搜索结果的设计图,下面截一张开发完成上线后的实图:

基本风格是模仿的百度搜索结果,绿色的分页略显小清新。

目前已采集并创建索引的文章约3W多篇,索引文件不算太大,查询速度非常棒。

刀不磨要生锈,人不学要落后。每天都要学一些新东西。

基本技术介绍:

还记得上一次做全文搜索是在2013年,主要核心设计与代码均是当时的架构师写的,自己只能算是全程参与。

当时使用的是经典搭配:盘古分词+Lucene.net。

前几篇文章有说到,盘古分词已经很多年不更新了,我在SupportYun系统一直引用的JieBaNet来做分词技术。

那么是否也有成型的JieBaNet+Lucene.Net的全文搜索方案呢?

经过多番寻找,在GitHub上面找到一个简易的例子:https://github.com/anderscui/jiebaForLuceneNet

博主下面要讲的实现方案就是从这个demo得到的启发,大家有兴趣可以去看看这个demo。

博主使用的具体版本:Lucene.net 3.0.3.0 ,JieBaNet 0.38.3.0(做过简易的调整与扩展,前面文章有讲到)

首先我们对Lucene.Net的分词器Tokenizer、分析器Analyzer做一个基于JieBaNet的扩展。

1.基于LuceneNet扩展的JieBa分析器JiebaForLuceneAnalyzer

2.基于LuceneNet扩展的JieBa分词器:JiebaForLuceneTokenizer

理想如果不向现实做一点点屈服,那么理想也将归于尘土。

实现方案设计:

我们做全文搜索的设计时一定会考虑的一个问题就是:我们系统是分很多模块的,不同模块的字段差异很大,怎么才能实现同一个索引,既可以单个模块搜索又可以全站搜索,甚至按一些字段做条件来搜索呢?

这些也是SupportYun系统需要考虑的问题,因为目前的数据就天然的拆分成了活动、文章两个类别,字段也大有不同。博主想实现的是一个可以全站搜索(结果包括活动、文章),也可以在文章栏目/活动栏目分别搜索,并且可以按几个指定字段来做搜索条件。

要做一个这样的全文搜索功能,我们需要从程序设计上来下功夫。下面就介绍一下博主的设计方案:

一、索引创建

1.我们设计一个IndexManager来处理最基本的索引创建、更新、删除操作。

2.创建、更新使用到的标准数据类:IndexContent。

我们设计TableName(对应DB表名)、RowId(对应DB主键)、CollectTime(对应DB数据创建时间)、ModuleType(所属系统模块)、Title(检索标题)、IndexTextContent(检索文本)等六个基础字段,所有模块需要创建索引必须构建该6个字段(大家可据具体情况扩展)。

然后设计10个预留字段Tag1-Tag10,用以兼容各大模块其他不同字段。

预留字段的存储、索引方式可独立配置。

其中BaseIndexContent含有六个基础字段。

3.创建一个子模块索引构建器的接口:IIndexBuilder。

各子模块通过继承实现IIndexBuilder,来实现索引的操作。

4.下面我们以活动模块为例,来实现索引创建。

a)首先创建一个基于活动模块的数据类:ActivityIndexContent,可以将我们需要索引或存储的字段都设计在内。

b)我们再创建ActivityIndexBuilder并继承IIndexBuilder,实现其创建、更新、删除方法。

代码就不解释了,很简单。主要就是调用IndexManager来执行操作。

我们只需要在需要创建活动数据索引的业务点,构建ActivityIndexBuilder对象,并构建ActivityIndexContent集合作为参数,调用BuildIndex方法即可。

二、全文搜索

全文搜索我们采用同样的设计方式。

1.设计一个抽象的搜索类:BaseIndexSearch,所有搜索模块(包括全站)均需继承它来实现搜索效果。

几个protected abstract方法,是需要继承的子类来实现的。

其中为了实现搜索结果对命中关键词进行高亮显示,特引用了盘古分词的Highlighter。原则是此处应该是参照盘古分词的源码,自己使用JieBaNet来做实现的,由于工期较紧,直接引用了盘古。

2.我们设计一个IndexSearchResultItem,表示搜索结果的基类。

3.我们来看看具体的实现,先来看全站搜索的SearchService

是不是非常简单。由于我们此处搜索的是全站,结果展示直接用基类,取出基本字段即可。

4.再列举一个活动的搜索实现。

a)我们首先创建一个活动搜索结果类ActivityIndexSearchResultItem,继承自结果基类IndexSearchResultItem

b)然后创建活动模块的搜索服务:ActivityIndexSearch,同样需要继承BaseIndexSearch,这时候ActivityIndexSearch只需要相对全站搜索修改几个参数即可。

筛选条件加上模块=活动,返回结果数据类指定,活动特有字段返回赋值。

业务调用就非常简单了。

全站全文搜索:我们直接new IndexSearch(),然后调用其Search()方法

活动全文搜索:我们直接new ActivityIndexSearch(),然后调用其Search()方法

Search()方法几个参数:

///搜索文本内容

    /// 查询内容限制条件,默认为null,不限制条件.

    /// 对字段进行排序

    /// 查询结果当前页,默认为1

    /// 查询结果每页结果数,默认为20

如果我们用软能力而不是用技术能力来区分程序员的好坏 – 是不是有那么点反常和变态。


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:C#中的等值判断1(cctv5体育节目表)
下一篇:Jwt身份验证(jwt官方文档)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~