tags: Lucene


什么是Lucene??

Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引和查询索引,以及部分文本分析的引擎,Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎,Lucene在全文检索领域是一个经典的祖先,现在很多检索引擎都是在其基础上创建的,思想是相通的。

Lucene是根据关健字来搜索的文本搜索工具,只能在某个网站内部搜索文本内容,不能跨网站搜索

既然谈到了网站内部的搜索,那么我们就谈谈我们熟悉的百度、google那些搜索引擎又是基于什么搜索的呢....

从图上已经看得很清楚,baidu、google等搜索引擎其实是通过网络爬虫的程序来进行搜索的...


为什么我们要用Lucene?

在介绍Lucene的时候,我们已经说了:Lucene又不是搜索引擎,仅仅是在网站内部进行文本的搜索。那我们为什么要学他呢???

我们之前编写纳税服务系统的时候,其实就已经使用过SQL来进行站内的搜索..

既然SQL能做的功能,我们还要学Lucene,为什么呢???

我们来看看我们用SQL来搜索的话,有什么缺点:

  • (1)SQL只能针对数据库表搜索,不能直接针对硬盘上的文本搜索
  • (2)SQL没有相关度排名
  • (3)SQL搜索结果没有关健字高亮显示
  • (4)SQL需要数据库的支持,数据库本身需要内存开销较大,例如:Oracle
  • (5)SQL搜索有时较慢,尤其是数据库不在本地时,超慢,例如:Oracle

我们来看看在baidu中搜索Lucene为关键字搜索出的内容是怎么样的:

以上所说的,我们如果使用SQL的话,是做不到的。因此我们就学习Lucene来帮我们在站内根据文本关键字来进行搜索数据


我们如果网站需要根据关键字来进行搜索,可以使用SQL,也可以使用Lucene...那么我们Lucene和SQL是一样的,都是在持久层中编写代码的。。

快速入门

接下来,我们就讲解怎么使用Lucene了.....在讲解Lucene的API之前,我们首先来讲讲Lucene存放的究竟是什么内容...我们的SQL使用的是数据库中的内存,在硬盘中为DBF文件...那么我们Lucene内部又是什么东西呢??

Lucene中存的就是一系列的二进制压缩文件和一些控制文件,它们位于计算机的硬盘上, 这些内容统称为索引库,索引库有二部份组成:

  • (1)原始记录

    • 存入到索引库中的原始文本,例如:我是钟福成
  • (2)词汇表
    • 按照一定的拆分策略(即分词器)将原始记录中的每个字符拆开后,存入一个供将来搜索的表

也就是说:Lucene存放数据的地方我们通常称之为索引库,索引库又分为两部分组成:原始记录和词汇表....

原始记录和词汇表

当我们想要把数据存到索引库的时候,我们首先存入的是将数据存到原始记录上面去....

又由于我们给用户使用的时候,用户使用的是关键字来进行查询我们的具体记录。因此,我们需要把我们原始存进的数据进行拆分!将拆分出来的数据存进词汇表中

词汇表就是类似于我们在学Oracle中的索引表,拆分的时候会给出对应的索引值。

一旦用户根据关键字来进行搜索,那么程序就先去查询词汇表中有没有该关键字,如果有该关键字就定位到原始记录表中,将符合条件的原始记录返回给用户查看

我们查看以下的图方便理解:

到了这里,有人可能就会疑问:难道原始记录拆分的数据都是一个一个汉字进行拆分的吗??然后在词汇表中不就有很多的关键字了???

其实,我们在存到原始记录表中的时候,可以指定我们使用哪种算法来将数据拆分,存到词汇表中.....我们的图是Lucene的标准分词算法,一个一个汉字进行拆分。我们可以使用别的分词算法,两个两个拆分或者其他的算法。

编写第一个Lucene程序

首先,我们来导入Lucene的必要开发包:

  • lucene-core-3.0.2.jar【Lucene核心】
  • lucene-analyzers-3.0.2.jar【分词器】
  • lucene-highlighter-3.0.2.jar【Lucene会将搜索出来的字,高亮显示,提示用户】
  • lucene-memory-3.0.2.jar【索引库优化策略】

创建User对象,User对象封装了数据....


/*** Created by ozc on 2017/7/12.*/
public class User {private String id ;private String userName;private String sal;public User() {}public User(String id, String userName, String sal) {this.id = id;this.userName = userName;this.sal = sal;}public String getId() {return id;}public void setId(String id) {this.id = id;}public String getUserName() {return userName;}public void setUserName(String userName) {this.userName = userName;}public String getSal() {return sal;}public void setSal(String sal) {this.sal = sal;}
}复制代码

我们想要使用Lucene来查询出站内的数据,首先我们得要有个索引库吧!于是我们先创建索引库,将我们的数据存到索引库中

创建索引库的步骤:

  • 1)创建JavaBean对象
  • 2)创建Docment对象
  • 3)将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同
  • 4)创建IndexWriter对象
  • 5)将Document对象通过IndexWriter对象写入索引库中
  • 6)关闭IndexWriter对象
@Testpublic void createIndexDB() throws Exception {//把数据填充到JavaBean对象中User user = new User("1", "钟福成", "未来的程序员");//创建Document对象【导入的是Lucene包下的Document对象】Document document = new Document();//将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同/*** 向Document对象加入一个字段* 参数一:字段的关键字* 参数二:字符的值* 参数三:是否要存储到原始记录表中*      YES表示是*      NO表示否* 参数四:是否需要将存储的数据拆分到词汇表中*      ANALYZED表示拆分*      NOT_ANALYZED表示不拆分** */document.add(new Field("id", user.getId(), Field.Store.YES, Field.Index.ANALYZED));document.add(new Field("userName", user.getUserName(), Field.Store.YES, Field.Index.ANALYZED));document.add(new Field("sal", user.getSal(), Field.Store.YES, Field.Index.ANALYZED));//创建IndexWriter对象//目录指定为E:/createIndexDBDirectory directory = FSDirectory.open(new File("E:/createIndexDB"));//使用标准的分词算法对原始记录表进行拆分Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);//LIMITED默认是1W个IndexWriter.MaxFieldLength maxFieldLength = IndexWriter.MaxFieldLength.LIMITED;/*** IndexWriter将我们的document对象写到硬盘中** 参数一:Directory d,写到硬盘中的目录路径是什么* 参数二:Analyzer a, 以何种算法来对document中的原始记录表数据进行拆分成词汇表* 参数三:MaxFieldLength mfl 最多将文本拆分出多少个词汇** */IndexWriter indexWriter = new IndexWriter(directory, analyzer, maxFieldLength);//将Document对象通过IndexWriter对象写入索引库中indexWriter.addDocument(document);//关闭IndexWriter对象indexWriter.close();}复制代码

程序执行完,我们就会在硬盘中见到我们的索引库。

那我们现在是不知道记录是否真真正正存储到索引库中的,因为我们看不见。索引库存放的数据放在cfs文件下,我们也是不能打开cfs文件的

于是,我们现在用一个关键字,把索引库的数据读取。看看读取数据是否成功。

根据关键字查询索引库中的内容:

  • 1)创建IndexSearcher对象
  • 2)创建QueryParser对象
  • 3)创建Query对象来封装关键字
  • 4)用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准
  • 5)获取符合条件的编号
  • 6)用indexSearcher对象去索引库中查询编号对应的Document对象
  • 7)将Document对象中的所有属性取出,再封装回JavaBean对象中去,并加入到集合中保存,以备将之用
@Testpublic void findIndexDB() throws Exception {/*** 参数一: IndexSearcher(Directory path)查询以xxx目录的索引库** */Directory directory = FSDirectory.open(new File("E:/createIndexDB"));//创建IndexSearcher对象IndexSearcher indexSearcher = new IndexSearcher(directory);//创建QueryParser对象/*** 参数一: Version matchVersion 版本号【和上面是一样的】* 参数二:String f,【要查询的字段】* 参数三:Analyzer a【使用的拆词算法】* */Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_30);QueryParser queryParser = new QueryParser(Version.LUCENE_30, "userName", analyzer);//给出要查询的关键字String keyWords = "钟";//创建Query对象来封装关键字Query query = queryParser.parse(keyWords);//用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准TopDocs topDocs = indexSearcher.search(query, 100);//获取符合条件的编号for (int i = 0; i < topDocs.scoreDocs.length; i++) {ScoreDoc scoreDoc = topDocs.scoreDocs[i];int no = scoreDoc.doc;//用indexSearcher对象去索引库中查询编号对应的Document对象Document document = indexSearcher.doc(no);//将Document对象中的所有属性取出,再封装回JavaBean对象中去String id = document.get("id");String userName = document.get("userName");String sal = document.get("sal");User user = new User(id, userName, sal);System.out.println(user);}
复制代码

效果:


进一步说明Lucene代码

我们的Lucene程序就是大概这么一个思路:将JavaBean对象封装到Document对象中,然后通过IndexWriter把document写入到索引库中。当用户需要查询的时候,就使用IndexSearcher从索引库中读取数据,找到对应的Document对象,从而解析里边的内容,再封装到JavaBean对象中让我们使用


如果您觉得这篇文章帮助到了您,可以给作者一点鼓励

Lucene第一篇【介绍Lucene、快速入门】相关推荐

  1. SpringBoot+Lucene第一篇——引出Lucene

    Lucene的学习第一篇--引出Lucene 一:需求场景提出: 1:在指定(10个)不同名字,不同内容的word文档中,进行任意指定搜索. 比如:搜索哪个文档中有:"高富帅",& ...

  2. 《Ansible权威指南 》一 第一篇 Part 1 基础入门篇

    本节书摘来自华章出版社<Ansible权威指南 >一书中的第1章,第1.1节,李松涛 魏 巍 甘 捷 著更多章节内容可以访问云栖社区"华章计算机"公众号查看. 第一篇 ...

  3. .NET Core实战项目之CMS 第六章 入门篇-Vue的快速入门及其使用

    写在前面 上面文章我给大家介绍了Dapper这个ORM框架的简单使用,大伙会用了嘛!本来今天这篇文章是要讲Vue的快速入门的,原因是想在后面的文章中使用Vue进行这个CMS系统的后台管理界面的实现.但 ...

  4. .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了

    写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...

  5. 负载均衡原理剖析与实践:负载均衡第一篇-介绍篇

    负载均衡第一篇-介绍篇   系列文章索引: 负载均衡第一篇-介绍篇 负载均衡第二篇-负载均衡基础知识普及   前言:相信朋友们对负载均衡应该不陌生了!特别是对搞运维的朋友!可能很多的技术人员认为,负载 ...

  6. JAVA程序设计-头歌实训-------# 第一阶段 Java语言快速入门

    第一阶段 Java语言快速入门 第1关:Java程序的基本框架:Hello Java World! 任务描述 本关的任务是编写你人生中第一个Java程序,从此开启你的Java实训之旅,显示效果如下: ...

  7. 牛客网刷题之SQL篇:非技术快速入门39T

    导航 前序 一.简单的关键字练习 1-10 二.知识点复习之 ==运算符== 1.算数运算符 2.比较运算符 3.逻辑运算符 4.位运算符 三.10-28T 0.简单题总结 1. SQL18 ==分组 ...

  8. c++做界面_Adobe Photoshop基本介绍②,快速入门界面

    Adobe Photoshop基本介绍②,快速入门界面.此篇文章意在讲解Adobe Photoshop界面的介绍.在本篇文章,up主会使用Adobe Photoshop CC 2018 作为讲解.(以 ...

  9. 第1讲韩顺平 PHP视频教程 zend framework zend介绍 zend快速入门 韩顺平php视频教程ppt 笔记心得

    韩顺平 PHP视频教程  zend framework  PPT笔记心得 本教程贯穿了两个软件公司常用的两个项目,数据采集系统和购物车,共分20讲从本质上深入浅出的分析了zend framework运 ...

最新文章

  1. mysql释放表空间
  2. 计算机尖端技术,不可思议的尖端技术:Top10
  3. 最长不下降子序列java代码_浅谈最长不下降子序列与最长上升子序列
  4. js 正则或_ES6之正则扩展
  5. 【机器学习入门到精通系列】正则化解决过拟合问题(附Iris-L1 正则化代码)
  6. Matlab | Matlab中使用imaqtool工具箱获取摄像头数据及如何安装(摄像头)硬件适配器的图像采集支持包
  7. 调查显示企业对 Linux 开发人才需求日渐增长
  8. 33条C#、.Net经典面试题目及答案[zt]
  9. 03 Oracle分区表
  10. pythontuple数据类型_数据类型-元组Tuple
  11. Linux Ubuntu 安装 anaconda3和 Pycharm 社区版本
  12. 基于abtest思想的流量切换(nginx lua redis)
  13. 漫画 | 面试的我 VS 真实的我
  14. [转载]XSS 攻擊常用腳本
  15. 位置采集[置顶] iPhone手机上的GPS位置信息采集与分享应用
  16. ASP.NET对验证控件的一些整理(一)
  17. Libre-SOC 系统级芯片
  18. flash跟随鼠标样式
  19. Elasticsearch 8.x 正式发布!
  20. JavaScript 运输公司计算运费,路程越远,运费的折扣越高

热门文章

  1. python语言入门u-[学习总结] python语言学习总结 (一)
  2. python基础代码事例-学习笔记:python3,代码。小例子习作(2017)
  3. 简明python教程 豆瓣-Python 有哪些入门学习方法和值得推荐的经典教材?
  4. python编程输入标准-Python练习题,,T1.编写程序,输入
  5. lua学习笔记之函数
  6. Map中的key,value null取值
  7. vim中搭建与sourceinsight类似功能
  8. mysql中的触发器
  9. 题目1549:货币问题
  10. 前一个参数作为下个参数结果