热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Lucene7.2.1系列(一)快速入门

lucene7,2,1,

系列文章:

Lucene系列(一)快速入门

Lucene系列(二)luke使用及索引文档的基本操作

Lucene系列(三)查询及高亮

Lucene是什么?

Lucene在维基百科的定义

Lucene是一套用于全文检索和搜索的开放源代码程序库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程序接口,能够做全文索引和搜索,在Java开发环境里Lucene是一个成熟的免费开放源代码工具;就其本身而论,Lucene是现在并且是这几年,最受欢迎的免费Java信息检索程序库

另外,Lucene不提供爬虫功能,如果需要获取内容需要自己建立爬虫应用。
Lucene只做索引和搜索工作。

Lucene官网

http://lucene.apache.org/

打开Luncene官网你会发现Lucene版本更新的太快了,现在最新的版本已经是7.2.1。不过这也变相说明了Luncene这个开源库的火爆。

Lucenesolr

我想提到Lucene,不得不提solr了。

很多刚接触Lucene和Solr的人都会问这个明显的问题:我应该使用Lucene还是Solr?

答案很简单:如果你问自己这个问题,在99%的情况下,你想使用的是Solr. 形象的来说Solr和Lucene之间关系的方式是汽车及其引擎。 你不能驾驶一台发动机,但可以开一辆汽车。 同样,Lucene是一个程序化库,您不能按原样使用,而Solr是一个完整的应用程序,您可以立即使用它。(参考:Lucene vs Solr)

全文检索是什么?

全文检索在百度百科的定义

全文数据库是全文检索系统的主要构成部分。所谓全文数据库是将一个完整的信息源的全部内容转化为计算机可以识别、处理的信息单元而形成的数据集合。全文数据库不仅存储了信息,而且还有对全文数据进行词、字、段落等更深层次的编辑、加工的功能,而且所有全文数据库无一不是海量信息数据库。

全文检索首先将要查询的目标文档中的词提取出来,组成索引,通过查询索引达到搜索目标文档的目的。这种先建立索引,再对索引进行搜索的过程就叫全文检索(Full-text Search)。

全文检索(Full-Text Retrieval)是指以文本作为检索对象,找出含有指定词汇的文本。

全面、准确和快速是衡量全文检索系统的关键指标。

关于全文检索,我们要知道:

  • 只处理文本。
  • 不处理语义。
  • 搜索时英文不区分大小写。
  • 结果列表有相关度排序。(查出的结果如果没有相关度排序,那么系统不知道我想要的结果在哪一页。我们在使用百度搜索时,一般不需要翻页,为什么?因为百度做了相关度排序:为每一条结果打一个分数,这条结果越符合搜索条件,得分就越高,叫做相关度得分,结果列表会按照这个分数由高到低排列,所以第1页的结果就是我们最想要的结果。)
    在信息检索工具中,全文检索是最具通用性和实用性的。

参考:https://zhuanlan.zhihu.com/p/25558228

全文检索和数据库搜索的区别

简单来说,这两者解决的问题是不一样。数据库搜索在匹配效果、速度、效率等方面都逊色于全文检索。下面我们的一个例子就能很清楚说明这一点。

Lucene实现全文检索流程是什么?

Lucene实现全文检索流程
全文检索的流程分为两大部分:索引流程搜索流程

  • 索引流程:即采集数据构建文档对象分析文档(分词)创建索引。
  • 搜索流程:即用户通过搜索界面创建查询执行搜索,搜索器从索引库搜索渲染搜索结果

我们在下面的一个程序中,对这个全文检索的流程会有进一步的了解。

Lucene实现向文档写索引并读取文档

截止2018/3/30,用到的jar包结为最新。

程序用到的数据下载地址:

链接:https://pan.baidu.com/s/1ccgrCCRBBGOL-fmmOLrxlQ

密码:vyof

  1. 创建Maven项目,并添加相关jar包依赖
    org.apache.lucene lucene-core 7.2.1    org.apache.lucene lucene-queryparser 7.2.1    org.apache.lucene lucene-analyzers-common 7.2.1 
  1. 向文档里写索引
package lucene_demo1; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; /** * *TODO 索引文件 * @author Snaiclimb * @date 2018年3月30日 * @version 1.8 */ public class Indexer { // 写索引实例 private IndexWriter writer; /** * 构造方法 实例化IndexWriter * * @param indexDir * @throws IOException */ public Indexer(String indexDir) throws IOException { //得到索引所在目录的路径 Directory directory = FSDirectory.open(Paths.get(indexDir)); // 标准分词器 Analyzer analyzer = new StandardAnalyzer(); //保存用于创建IndexWriter的所有配置。 IndexWriterConfig iwCOnfig= new IndexWriterConfig(analyzer); //实例化IndexWriter writer = new IndexWriter(directory, iwConfig); } /** * 关闭写索引 * * @throws Exception * @return 索引了多少个文件 */ public void close() throws IOException { writer.close(); } public int index(String dataDir) throws Exception { File[] files = new File(dataDir).listFiles(); for (File file : files) { //索引指定文件 indexFile(file); } //返回索引了多少个文件 return writer.numDocs(); } /** * 索引指定文件 * * @param f */ private void indexFile(File f) throws Exception { //输出索引文件的路径 System.out.println("索引文件:" + f.getCanonicalPath()); //获取文档,文档里再设置每个字段 Document doc = getDocument(f); //开始写入,就是把文档写进了索引文件里去了; writer.addDocument(doc); } /** * 获取文档,文档里再设置每个字段 * * @param f * @return document */ private Document getDocument(File f) throws Exception { Document doc = new Document(); //把设置好的索引加到Document里,以便在确定被索引文档 doc.add(new TextField("contents", new FileReader(f))); //Field.Store.YES:把文件名存索引文件里,为NO就说明不需要加到索引文件里去 doc.add(new TextField("fileName", f.getName(), Field.Store.YES)); //把完整路径存在索引文件里 doc.add(new TextField("fullPath", f.getCanonicalPath(), Field.Store.YES)); return doc; } public static void main(String[] args) { //索引指定的文档路径 String indexDir = "D:\\lucene\\dataindex"; ////被索引数据的路径 String dataDir = "D:\\lucene\\data"; Indexer indexer = null; int numIndexed = 0; //索引开始时间 long start = System.currentTimeMillis(); try { indexer = new Indexer(indexDir); numIndexed = indexer.index(dataDir); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { indexer.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } //索引结束时间 long end = System.currentTimeMillis(); System.out.println("索引:" + numIndexed + " 个文件 花费了" + (end - start) + " 毫秒"); } }

运行效果:
运行效果图
我们查看D:\lucene\dataindex文件夹。我们发现多了一些东西,这些东西就是我们马上用来全文搜索的索引。

//索引指定的文档路径 String indexDir = "D:\\lucene\\dataindex"; 

D:\lucene\dataindex文件夹

Mark博文:Lucene的索引文件格式(1)

  1. 全文检索测试
package lucene_demo1; import java.nio.file.Paths; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; /** * 根据索引搜索 *TODO * @author Snaiclimb * @date 2018年3月25日 * @version 1.8 */ public class Searcher { public static void search(String indexDir, String q) throws Exception { // 得到读取索引文件的路径 Directory dir = FSDirectory.open(Paths.get(indexDir)); // 通过dir得到的路径下的所有的文件 IndexReader reader = DirectoryReader.open(dir); // 建立索引查询器 IndexSearcher is = new IndexSearcher(reader); // 实例化分析器 Analyzer analyzer = new StandardAnalyzer(); // 建立查询解析器 /** * 第一个参数是要查询的字段; 第二个参数是分析器Analyzer */ QueryParser parser = new QueryParser("contents", analyzer); // 根据传进来的p查找 Query query = parser.parse(q); // 计算索引开始时间 long start = System.currentTimeMillis(); // 开始查询 /** * 第一个参数是通过传过来的参数来查找得到的query; 第二个参数是要出查询的行数 */ TopDocs hits = is.search(query, 10); // 计算索引结束时间 long end = System.currentTimeMillis(); System.out.println("匹配 " + q + " ,总共花费" + (end - start) + "毫秒" + "查询到" + hits.totalHits + "个记录"); // 遍历hits.scoreDocs,得到scoreDoc /** * ScoreDoc:得分文档,即得到文档 scoreDocs:代表的是topDocs这个文档数组 * * @throws Exception */ for (ScoreDoc scoreDoc : hits.scoreDocs) { Document doc = is.doc(scoreDoc.doc); System.out.println(doc.get("fullPath")); } // 关闭reader reader.close(); } public static void main(String[] args) { String indexDir = "D:\\lucene\\dataindex"; //我们要搜索的内容 String q = "Jean-Philippe sdsds Barrette-LaPierre"; try { search(indexDir, q); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }

上面我们搜索的是:"Jean-Philippe Barrette-LaPierre";即使你:"Jean-Philippe ssss Barrette-LaPierre"这样搜索也还是搜索到,以为Lucene对其进行了分词,对中文无效。
全文搜索

Lucene实现全文检索流程是什么?

我们刚刚实现的程序已经清楚地向我们展示了Lucene实现全文检索流程,我们再来回顾一下。
Lucene实现全文检索流程

  • 在Lucene中,采集数据(从网站爬取或连接数据库)就是为了创建索引,创建索引需要先将采集的原始数据加工为文档,再由文档分词产生索引。文档(Document) 中包含若干个Field域。
  • IndexWriter是索引过程的核心组件,通过IndexWriter可以创建新索引、更新索引、删除索引操作。IndexWriter需要通过Directory对索引进行存储操作。
  • Directory描述了索引的存储位置,底层封装了I/O操作,负责对索引进行存储。它是一个抽象类,它的子类常用的包括FSDirectory(在文件系统存储索引)、RAMDirectory(在内存存储索引)。
  • 在对Docuemnt中的内容索引之前需要使用分词器进行分词 ,分词的主要过程就是分词、过滤两步。 分词就是将采集到的文档内容切分成一个一个的词,具体应该说是将Document中Field的value值切分成一个一个的词。
    过滤包括去除标点符号、去除停用词(的、是、a、an、the等)、大写转小写、词的形还原(复数形式转成单数形参、过去式转成现在式等)。
  • 停用词是为节省存储空间和提高搜索效率,搜索引擎在索引页面或处理搜索请求时会自动忽略某些字或词,这些字或词即被称为Stop Words(停用词)。比如语气助词、副词、介词、连接词等,通常自身并无明确的意义,只有将其放入一个完整的句子中才有一定作用,如常见的“的”、“在”、“是”、“啊”等。
    Lucene中自带了StandardAnalyzer,它可以对英文进行分词。

参照:https://zhuanlan.zhihu.com/p/25558228

欢迎关注我的微信公众号(分享各种Java学习资源,面试题,以及企业级Java实战项目回复关键字免费领取):
微信公众号

Lucene我想暂时先更新到这里,仅仅这三篇文章想掌握Lucene是远远不够的。另外我这里三篇文章都用的最新的jar包,Lucene更新太快,5系列后的版本和之前的有些地方还是有挺大差距的,就比如为文档域设置权值的setBoost方法6.6以后已经被废除了等等。因为时间有限,所以我就草草的看了一下Lucene的官方文档,大多数内容还是看java1234网站的这个视频来学习的,然后在版本和部分代码上做了改进。截止2018/4/1,上述代码所用的jar包皆为最新。

最后推荐一下自己觉得还不错的Lucene学习网站/博客:

官方网站:Welcome to Apache Lucene

Github:Apache Lucene and Solr

Lucene专栏

搜索系统18:lucene索引文件结构

Lucene6.6的介绍和使用


推荐阅读
  • 原文网址:https:www.cnblogs.comysoceanp7476379.html目录1、AOP什么?2、需求3、解决办法1:使用静态代理4 ... [详细]
  • 在对WordPress Duplicator插件0.4.4版本的安全评估中,发现其存在跨站脚本(XSS)攻击漏洞。此漏洞可能被利用进行恶意操作,建议用户及时更新至最新版本以确保系统安全。测试方法仅限于安全研究和教学目的,使用时需自行承担风险。漏洞编号:HTB23162。 ... [详细]
  • Maven Web项目创建时JSP文件常见错误及解决方案
    Maven Web项目创建时JSP文件常见错误及解决方案 ... [详细]
  • 本文深入探讨了如何利用Maven高效管理项目中的外部依赖库。通过介绍Maven的官方依赖搜索地址(),详细讲解了依赖库的添加、版本管理和冲突解决等关键操作。此外,还提供了实用的配置示例和最佳实践,帮助开发者优化项目构建流程,提高开发效率。 ... [详细]
  • 在Java Web服务开发中,Apache CXF 和 Axis2 是两个广泛使用的框架。CXF 由于其与 Spring 框架的无缝集成能力,以及更简便的部署方式,成为了许多开发者的首选。本文将详细介绍如何使用 CXF 框架进行 Web 服务的开发,包括环境搭建、服务发布和客户端调用等关键步骤,为开发者提供一个全面的实践指南。 ... [详细]
  • C++ 开发实战:实用技巧与经验分享
    C++ 开发实战:实用技巧与经验分享 ... [详细]
  • Presto:高效即席查询引擎的深度解析与应用
    本文深入解析了Presto这一高效的即席查询引擎,详细探讨了其架构设计及其优缺点。Presto通过内存到内存的数据处理方式,显著提升了查询性能,相比传统的MapReduce查询,不仅减少了数据传输的延迟,还提高了查询的准确性和效率。然而,Presto在大规模数据处理和容错机制方面仍存在一定的局限性。本文还介绍了Presto在实际应用中的多种场景,展示了其在大数据分析领域的强大潜力。 ... [详细]
  • Android中将独立SO库封装进JAR包并实现SO库的加载与调用
    在Android开发中,将独立的SO库封装进JAR包并实现其加载与调用是一个常见的需求。本文详细介绍了如何将SO库嵌入到JAR包中,并确保在外部应用调用该JAR包时能够正确加载和使用这些SO库。通过这种方式,开发者可以更方便地管理和分发包含原生代码的库文件,提高开发效率和代码复用性。文章还探讨了常见的问题及其解决方案,帮助开发者避免在实际应用中遇到的坑。 ... [详细]
  • 在日常的项目开发中,测试环境和生产环境通常采用HTTP协议访问服务。然而,从浏览器的角度来看,这种访问方式会被标记为不安全。为了提升安全性,当前大多数生产环境已经转向了HTTPS协议。本文将详细介绍如何在Spring Boot应用中配置SSL证书,以实现HTTPS安全访问。通过这一过程,不仅可以增强数据传输的安全性,还能提高用户对系统的信任度。 ... [详细]
  • 本文详细介绍了如何在Java Web服务器上部署音视频服务,并提供了完整的验证流程。以AnyChat为例,这是一款跨平台的音视频解决方案,广泛应用于需要实时音视频交互的项目中。通过具体的部署步骤和测试方法,确保了音视频服务的稳定性和可靠性。 ... [详细]
  • 在前文探讨了Spring如何为特定的bean选择合适的通知器后,本文将进一步深入分析Spring AOP框架中代理对象的生成机制。具体而言,我们将详细解析如何通过代理技术将通知器(Advisor)中包含的通知(Advice)应用到目标bean上,以实现切面编程的核心功能。 ... [详细]
  • Netty框架中运用Protobuf实现高效通信协议
    在Netty框架中,通过引入Protobuf来实现高效的通信协议。为了使用Protobuf,需要先准备好环境,包括下载并安装Protobuf的代码生成器`protoc`以及相应的源码包。具体资源可从官方下载页面获取,确保版本兼容性以充分发挥其性能优势。此外,配置好开发环境后,可以通过定义`.proto`文件来自动生成Java类,从而简化数据序列化和反序列化的操作,提高通信效率。 ... [详细]
  • 在处理遗留数据库的映射时,反向工程是一个重要的初始步骤。由于实体模式已经在数据库系统中存在,Hibernate 提供了自动化工具来简化这一过程,帮助开发人员快速生成持久化类和映射文件。通过反向工程,可以显著提高开发效率并减少手动配置的错误。此外,该工具还支持对现有数据库结构进行分析,自动生成符合 Hibernate 规范的配置文件,从而加速项目的启动和开发周期。 ... [详细]
  • CentOS 7环境下Jenkins的安装与前后端应用部署详解
    CentOS 7环境下Jenkins的安装与前后端应用部署详解 ... [详细]
  • 在尝试为 Unity 编译一个简单的 Java 库时,运行 `ant jar` 命令后遇到了 Java I/O 异常。具体错误信息为“无法启动程序 ${aAPT},错误代码 2”,这通常表示指定的文件或目录不存在。此问题可能是由于环境配置不正确或路径设置有误导致的。建议检查相关路径和环境变量,确保所有依赖项都已正确安装和配置。 ... [详细]
author-avatar
我们要疯_475
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有