[lucene]使用lucene建立网站搜索服务

news/2024/7/8 7:24:14 标签: lucene, string, 全文检索, 数据库, object, class
class="baidu_pl">
class="article_content clearfix">
class="htmledit_views">

class="tags" href="/tags/LUCENE.html" title=lucene>lucene是一个class="tags" href="/tags/QuanWenJianSuo.html" title=全文检索>全文检索引擎(非分布式),使用java编写并且可以很方便的嵌入到各种系统中以实现class="tags" href="/tags/QuanWenJianSuo.html" title=全文检索>全文检索功能,其通过对字符串进行分词,然后针对分词结果分别建立索引,存入内存或者磁盘,以提供搜索服务,这个功能用起来就像是一个单机版的google,模糊匹配的结果会被展示给用户。应用class="tags" href="/tags/LUCENE.html" title=lucene>lucene较为出名的就包括了eclipse的帮助系统。

很多时候搜索这个概念会含糊不清,通常意义上对于一个网站的搜索功能是针对于从class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库中捞取数据并通过freemarker或者velocity渲染模板后展示出来,然后搜索的另一个含义,是针对于文件系统而言,将文件的内容进行搜索并读取文件展示出来。那么对于class="tags" href="/tags/LUCENE.html" title=lucene>lucene而言,显然更大的用于之地在于后者,虽然前者的功能也是能够实现。
我们可以想象google的服务器不断的定时dump全球Internet的网页,然后放入自己的存储区域,通过检索评级等一系列的复杂算法,建立针对于关键字的索引,当用户输入关键字进行查询的时候,她会根据建立的索引以及评级等信息进行相似度的判断并展现出查询结果。当然具体的过程会远远比这个复杂。这里要说的是建立搜索的这个概念,从简单的class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库查询的思想出脱离出来,建立一个class="tags" href="/tags/QuanWenJianSuo.html" title=全文检索>全文检索的概念。

索引可以理解成现实中书籍的目录,通过这个目录可以很快的定位到具体的页数,拿到想要的结果。这个和class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库的索引是一样的功能,都是为了提高效率,然后class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库却无法实现一个高效的模糊匹配,通常而言的%like%语句,是一条一条的数据比对类似于书籍的翻页过程,这样的效率是极其低下而且对于class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库系统而言是很大的性能耗费,尤其是当有多个关键字的时候,多个%like%的查询条件足以让DBA疯掉。

所以对于模糊匹配的查询而言,高效而准确是一个关键的因素。而class="tags" href="/tags/LUCENE.html" title=lucene>lucene的优势就是通过对文本进行分词,通过分词得到一系列的关键字以用于建立索引,同时使用自己默认的socre相关度算法进行排序,通常而言如果对于搜索结果有自己特殊的排序要求,可以在使用class="tags" href="/tags/LUCENE.html" title=lucene>lucene建立索引之前,先将数据排好序,可以防止class="tags" href="/tags/LUCENE.html" title=lucene>lucene默认的排序之外再次进行排序操作。

对于原理性的知识,可以参看网络上的一些文章,google一下看到很多写的都不错,个人不是很擅长写这种原理性的东西,所以下面做一个小实验,来熟悉一下具体的class="tags" href="/tags/LUCENE.html" title=lucene>lucene step by step

 

我们的需求是针对于一个网站的帮助系统开发一个搜索功能,用户输入自己希望搜索的问题或者关键字,我们通过class="tags" href="/tags/LUCENE.html" title=lucene>lucene进行搜索并展示结果给用户。

 

就是这样简单的一个需求,假设我们的帮助系统的文档是存放在class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库中的,这个数据量在百这个级别,很小的一个数据量。我们先模拟一个小数据量来实现这个功能,如果数据量是百万级那需要进行分布式的索引建立和搜索,那将涉及到其他额外的很多条件和问题解决方案。

我们希望通过这个系统的开发,不但能解决当前的帮助系统的问题,还可以一定程度上解决一些数据量较小的其他搜索问题,所以是势必需要我们去开发一个通用的中间件,并且通过一定的控制手段来注入特定的业务。

要建立索引,我们需要知道面对的数据对象是谁?哪张表?在哪些字段上建立索引?这几个是关键因素,当然还包括了索引文件存放位置等小问题暂且掠过。这几个关键的因素我们需要注入到我们开发的中间件中,通过配置注入的方式隔离具体的业务代码交织。

怎么做呢?如何去从class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库中获取数据并建立索引呢?索引文件以多大的频率更新?

看看代码:

 

这个是我们的中间件,提供的是索引建立、索引更新和搜索服务,其中有几个变量如className指明了要针对哪个Do对象所对应的表来建立class="tags" href="/tags/QuanWenJianSuo.html" title=全文检索>全文检索,fieldsStr指明了需要建立索引的字段,以逗号分开,其他的参数也都很简单。

我们需要根据配置的字段去查询class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库已完成索引的建立工作,那么如何获取呢?我们说过不希望通过显示的业务代码来完成,所以这里使用了前段时间开发的一个jdbcTemplate的封装抽象类,其中的查询字段列表的方法来得到特定字段值的列表,为了不显示的使用业务DAO,我们使用了一个匿名内部类来完成。具体的过程可以参见前面的文章。其中与之有所不同的是,在删除索引的时候,我们需要有一个类似于记录ID的标志位来标记唯一约束,以防止误删的情况,这里由于数据来自于class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库,所以很自然的我们选择使用class="tags" href="/tags/ShuJuKu.html" title=数据库>数据库记录ID,如果用户配置的索引串中没有配置ID,那我们将通过注解的方式自动获取其配置在DO类中的ID名称,如果注解中也没配置,那么将使用默认的名称“id”。

看看我们的注解:

看看用法:

配置文件中,我们添加相关的配置:

为了完成自动刷新,我们添加配置任务:

 

这样就完成了开发工作。系统启动先建立索引,然后每隔15分钟将刷新一次索引。自动刷新我们的策略是删除所有的索引,重新建立索引,这个特别针对于数据量较小的操作,如果数据量稍微大一些,不推荐采用这种方式,我们需要进行一个自动识别的工作,只刷新变更过的记录,而不要过多的开销系统来重新全部重建。这里由于数据量较小,所以为了方便,我们直接删除所有索引重新建立。在后续的工作中,我们将重点研究如何精准刷新。

看看单元测试代码:

 

万里长征只走了第一步,剩下的事情还有很多,这个只是最简单的一个例子,万事开头难,在熟练应用的基础上进行二次开发或者源码分析将是接下来的主要工作思路。

 


http://www.niftyadmin.cn/n/1639127.html

相关文章

Elasticsearch性能优化建议

之前公司项目中有使用Elasticsearch存储日志,当时使用的功能简单,并没有深入了解Elasticsearch,但是对于该支持文本搜索的存储架构还是很感兴趣,最近因为想在一个新项目中采用ELK(ElasticsearchLogstashKibana&#xf…

elasticsearch 查询优化建议

最近在做一些索引相关的优化测试,顺便记录一下测试以及效果 1:优化mapping 主要包括 doc_values , index , norms , type的keyword和text // 效果明显 doc_values属性 用于把数据序列化到磁盘,使索引结构更紧密 默认为tru…

[lucene第二季]利用缓存辅助精确更新索引

在上一篇的lucene的入门篇中,我们编写了一个帮助系统,从数据库中将具体的信息获取出来并使用CJKAnalyzer分词后建立索引,提供针对于关键字的搜索服务,其中我们采用定时器的方式每隔10分钟更新一次索引,更新的方式为先删…

[lucene]倒排笔记

lucene的倒排算法相关笔记: 计算文章中关键字出现的位置以及出现频率,以便于精准定位。 百度的定义:用记录的非主属性查找记录而组织的文件,叫倒排文件,或者 倒排索引,次索引 lucene不使用B树&#xff0…

[ElasticSearch]Java API 之 滚动搜索(Scroll API)

一般搜索请求都是返回一"页"数据,无论数据量多大都一起返回给用户,Scroll API可以允许我们检索大量数据(甚至全部数据)。Scroll API允许我们做一个初始阶段搜索并且持续批量从Elasticsearch里拉取结果直到没有结果剩下。…

mysql数据实时同步到Elasticsearch

业务需要把mysql的数据实时同步到ES,实现低延迟的检索到ES中的数据或者进行其它数据分析处理。本文给出以同步mysql binlog的方式实时同步数据到ES的思路, 实践并验证该方式的可行性,以供参考。 mysql binlog日志 mysql的binlog日志主要用于数据库的主…

[拦截器]关于拦截方法调用其他内部方法无法被拦截问题的解决

拦截器的实现原理很简单,就是动态代理,实现AOP机制。当外部调用被拦截bean的拦截方法时,可以选择在拦截之前或者之后等条件执行拦截方法之外的逻辑,比如特殊权限验证,参数修正等操作。但是如果现在一个需求是&#xff…

使用Logstash来实时同步MySQL数据到ES

本篇我们来实战从MYSQL里直接同步数据 一、首先下载和你的ES对应的logstash版本,本篇我们使用的都是6.1.1 下载后使用logstash-plugin install logstash-input-jdbc 命令安装jdbc的数据连接插件 二、新增mysqltoes.conf文件,配置Input和output参数如下&…