全文检索技术Lucene
一. Lucene 简介
1. Lucene 是什么
Lucene 是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎。说到底它是一个信息检索程序库,而不是应用产品。因此它并不像百度或者 google 那样,拿来就能用,它只是提供了一种工具让你能实现这些产品。
2 . Lucene 能做什么
要回答这个问题,先要了解 lucene 的本质。实际上 lucene 的功能很单一,说到底,就是我们给它若干个字符串,然后它为我们提供一个全文搜索服务,最后告诉我们要搜索的关键词出现在哪里。知道了这个本质,我们就可以发挥想象做任何符合这个条件的事情了。比如我们可以把站内新闻都索引了,做个资料库;也可以把一个数据库表的若干个字段索引起来,那就不用再担心因为“%like%”而锁表了;学完 lucene,你也可以写个自己的搜索引擎了……
3 . Lucene 速度测试
下面给出一些测试数据,如果你觉得可以接受,那么可以选择。
测试一:250 万记录,300M 左右文本,生成索引 380M 左右,800 线程下平均处理时间 300ms。
测试二:37000 记录,索引数据库中的两个 varchar 字段,索引文件2.6M,800 线程下平均处理时间 1.5ms。
二. 深入lucene
1. 为什么 lucene 这么快
1、倒排索引
2、压缩算法
3、二元搜索
2. 倒排序索引
它是根据属性的值来查找记录。
这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址由于不是由记录来确定属性值,
而是由属性值来确定记录的位置,因而称为倒排索引(invertedindex) 如下简单的例子
3. 工作方式
Lucene 提供的服务实际包含两部分:一入一出。所谓入是写入,即将你提供的源(本质是字符串)写入索引或者将其从索引中删除;所谓出是读出,即向用户提供全文搜索服务,让用户可以通过关键词定位源。
4. 写入流程
- 源字符串首先经过 analyzer 处理,包括:分词,分成一个个单词去除 stopword(可选)。
- 将源中需要的信息加入 Document 的各个 Field(信息域)中,并把需要索引的 Field 索引起来,把需要存储的 Field 存储起来。
- 将索引写入磁盘。
5. 读出流程
- 用户提供搜索关键词,经过 analyzer 处理。
- 对处理后的关键词搜索它的索引,找出对应的 Document。
- 用户根据需要从找到的 Document 中提取需要的 Field。
6. Docement
用户提供的源是一条条记录,它们可以是文本文件, 字符串或者数据库表的一条记录等等。一条记录经过索引之后,就是以一个Document 的形式存储在索引文件中的, 用户进行搜索也是以Document 列表的形式返回。
7. Field
一个 Document 可以包含多个信息域,例如一篇文章可以包含“标题”、“正文”、“最后修改时间”等信息域,这些信息域就是通过 Field在 Document 中存储的。Field 有两个属性可选:存储和索引。通过存储属性你可以控制是否对这个 Field 进行存储;通过索引属性你可以控制是否对该Field 进行索引。这看起来似乎有些废话,事实上对这两个属性的正确组合很重要。
8. 实现原理
文本倒排处理:
Lucene 整体使用如图所示:
9. 环境配置
9-1 下载jar包的方式
下载 lucene jar
官网:https://lucene.apache.org/
导入 jar 到项目中
我下载的为7-5-0版本的zip,架包引入下面依赖中的jar就行,但是org.apache.commons.io
必须从依赖库里面引入,本人建议你可以建个maven项目,然后只引入org.apache.commons.io
依赖,其他的几个直接把你下载的zip解压,找到里面的对应架包引入就行,因为maven库里面的版本较低
9-2或者加入依赖,相关依赖如下:
<dependencies><!--测试环境--><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.12</version><scope>compile</scope></dependency><!-- https://mvnrepository.com/artifact/org.apache.directory.studio/org.apache.commons.io --><dependency><groupId>org.apache.directory.studio</groupId><artifactId>org.apache.commons.io</artifactId><version>2.4</version></dependency><!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>4.10.3</version></dependency><!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-queryparser</artifactId><version>4.10.3</version></dependency><!-- http://mvnrepository.com/artifact/org.apache.lucene/lucene-core --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>4.10.3</version></dependency>
</dependencies>
10. 创建索引
Lucene的最重要的工作流程就是先给你查询的东西创建索引,也即给你要查询的数据按照Lucene的方式创建索引,这样才会搜索的更快,使用第一步让我们给数据创建索引,直接上代码啦!!! 注释写的比较啰嗦.
两个成员变量:
//要搜索的目录路径
String pathSearch = "C://Users//威威//Desktop//课堂内容//第15周//day 5";
//索引要存放的路径
String pathIndex = "C://Users//威威//Desktop//课堂内容//第16周//day 5//testLucene";
正式的建索引代码:
@Testpublic void createIndex() throws IOException {//索引存放的目录文件夹File indexRepositoryFile = new File(pathIndex);//得到目录的文件路径(不能直接用上面的path,不然会报错)Path directoryPath = indexRepositoryFile.toPath();//lucene进行搜索的目录Directory directory = FSDirectory.open(directoryPath);//准备你想要搜索的目录文件File searchFiles = new File(pathSearch);//获取一个标准分词器Analyzer analyzer = new StandardAnalyzer();//配置indexWriterConfig//IndexWriterConfig indexWConfig = new IndexWriterConfig();IndexWriterConfig indexWConfig = new IndexWriterConfig(analyzer);//指定索引写入的模式indexWConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);//通过索引目录与配置信息得到writerIndexWriter writer = new IndexWriter(directory, indexWConfig);//遍历读取文件目录pathSearch里的所有文件,非常重要,如果直接遍历杜会报错(文件存在,但它是个目录)Collection<File> files = FileUtils.listFiles(searchFiles, TrueFileFilter.INSTANCE,TrueFileFilter.INSTANCE);//遍历读取目录里的所有文件for(File file : files){//得到文件名String fileName = file.getName();//文件内容String fileContent = FileUtils.readFileToString(file);//文件路径String filePath = file.getPath();//文件大小Long fileSize = FileUtils.sizeOf(file);//创建一个document对象Document document = new Document();// 向Document对象中添加域信息// 参数:1、域的名称;2、域的值;3、是否存储;Field nameField = new TextField("name",fileName,Store.YES );Field contentField = new TextField("content", fileContent, Store.YES);// storedFiled默认存储Field pathField = new StoredField("path",filePath );Field sizeField = new StoredField("size",fileSize );// 将域添加到document对象中document.add(nameField);document.add(contentField);document.add(pathField);document.add(sizeField);//将信息写入到检索库中writer.addDocument(document);}//关闭indexWriterwriter.close();}
点击运行会在你索引目录生成索引文件:
11. 查询索引
上面索引建立好了,此时你要全文检索,检索已经建好索引的目录就行了,不再索引源文件的目录.
正式搜索代码:
@Testpublic void search() throws IOException, ParseException {//指定索引的目录并打开,路径不能直接给,必须转化一下File file = new File(pathIndex);Path path = file.toPath();Directory directory = FSDirectory.open(path);//得到一个基础分词器,查询也需要分词操作,假如用户输入的内容很长Analyzer analyzer = new StandardAnalyzer();IndexReader indexReader = DirectoryReader.open(directory);//创建IndexSearch对象IndexSearcher indexSearcher = new IndexSearcher(indexReader);//创建一个分析器QueryParser parser = new QueryParser("content",analyzer);//要查询的东西Query query = parser.parse("用");/*// 创建一个查询对象TermQuery termQuery = new TermQuery(new Term("name", "crm"));*/// 执行查询// 返回的最大值,在分页的时候使用TopDocs topDocs = indexSearcher.search(query, 10);// 取查询结果总数量System.out.println("总共的查询结果:" + topDocs.totalHits);// 查询结果,就是documentID列表ScoreDoc[] scoreDocs = topDocs.scoreDocs;for (ScoreDoc scoreDoc : scoreDocs) {// 取对象document的对象idint docID = scoreDoc.doc;// 相关度得分float score = scoreDoc.score;// 根据ID去document对象Document document = indexSearcher.doc(docID);/*System.out.println("相关度得分:" + score);System.out.println("");System.out.println("文件的名字: "+document.get("name"));System.out.println("");*/// 另外的一种使用方法System.out.println(document.getField("content").stringValue());System.out.println(document.get("path"));System.out.println();System.out.println("=======================");}indexReader.close();}
12. Lucene的其他功能
12-1 分词器
Lucene 自带的 StandardAnalyzer 分词器,只能对英语进行分词。
在对中文进行分词的时候采用了一元分词,即每一个中文作为一个词,
如“我是中国人”,则分词结果为“我”,“是”,“中”,“国”,“人”,
可以看出分词效果很差。在这里推荐一个比较好用的中文分词器
IKAnalyzer。
12-2 停用词
停用词是指在信息检索中,为节省存储空间和提高搜索效率,在
处理自然语言数据(或文本)之前或之后会自动过滤掉某些字或词,
这些字或词即被称为 Stop Words(停用词)。比如中文中“了”, “么”,
“呢”,“的”等意义不大且在一篇文章中出现频率又很高的词,又比
如英文中的”for”,”in”,”it”,”a”,”or”等词。
在使用 IKAnalyzer 分词器的时候,可以在 IKAnalyzer.cfg.xml
里配置相关信息,如下图:
<?xml version="1.0" encoding="UTF-8"?>
<properties><comment>IK Analyzer 扩展配置</comment><!--用户在这可以配置自己的扩展字典--><entry key="ext_dict">ext_dict;</entry><!--用户可以在这里配置自己的停止词字典--><entry key="ext_stopwords">stopword.dic;chinese_stopword.dic</entry>
</properties>
12-2 高亮-Highlighter
高亮是什么?来看一下百度就知道了
红色的就是关键词高亮显示了,引入里面的高亮jar包就行了,自己可以设置.
三. Lucene相关概念补充
1. Field属性
Field 是文档中的域,包括 Field 名和 Field 值两部分,一个文档可以包括多个 Field,Document 只是 Field 的一个承载体,Field值即为要索引的内容,也是要搜索的内容。
- 是否分词(tokenized)
- 是:作分词处理,即将 Field 值进行分词,分词的目的是为了索引。比如:商品名称、商品简介等,这些内容用户要输入关键字搜索,由于搜索的内容格式大、内容多需要分词后将语汇单元索引。
- 否:不作分词处理比如:商品 id、订单号、身份证号等
- 是否索引(indexed)
- 是:进行索引。将 Field 分词后的词或整个 Field 值进行索引,索引的目的是为了搜索比如:商品名称、商品简介分词后进行索引,订单号、身份证号不用分词但也要索引,这些将来都要作为查询条件。
- 否:不索引。该域的内容无法搜索到比如:商品 id、文件路径、图片路径等,不用作为查询条件的不用索引。
- 是否存储(stored)
- 是:将 Field 值存储在文档中,存储在文档中的 Field 才可以从
Document 中获取。比如:商品名称、订单号,凡是将来要从 Document 中获取的 Field都要存储。 - 否:不存储 Field 值,不存储的 Field 无法通过 Document 获取
比如:商品简介,内容较大不用存储。如果要向用户展示商品简介可以从系统的关系数据库中获取商品简介。如果需要商品描述,则根据搜索出的商品 ID 去数据库中查询,然后显示出商品描述信息即可。
- 是:将 Field 值存储在文档中,存储在文档中的 Field 才可以从
2. Field 常用类型
开发中常用 的 Filed 类型,注意 Field 的属性,根据需求选择:
3. 例子
- 图书 id:
- 是否分词:不用分词,因为不会根据商品 id 来搜索商品
- 是否索引:不索引,因为不需要根据图书 ID 进行搜索
- 是否存储:要存储,因为查询结果页面需要使用 id 这个值
- 图书名称:
- 是否分词:要分词,因为要将图书的名称内容分词索引,根据关键搜索图书名称抽取的词。
- 是否索引:要索引。
- 是否存储:要存储
- 图书价格:
- 是否分词:要分词,lucene 对数字型的值只要有搜索需求的都要分词和索引,因为 lucene 对数字型的内容要特殊分词处理,本例子可能要根据价格范 围搜索,需要分词和索引。
- 是否索引:要索引
- 是否存储:要存储
- 图书图片地址:
- 是否分词:不分词
- 是否索引:不索引
- 是否存储:要存储
- 图书描述:
- 是否分词:要分词
- 是否索引:要索引
- 是否存储:因为图书描述内容量大,不在查询结果页面直接显示,不存储。 不存储是来不在 lucene 的索引文件中记录,节省 lucene的索引文件空间, 如果要在详情页面显示描述,思路: 从 lucene中取出图书的 id,根据图书的 id 查询关系数据库中 book 表 得到描述信息。
全文检索技术Lucene相关推荐
- 全文检索技术Lucene入门和学习、与数据库数据结合的demo实现
首先,要非常感谢 博客园的 "觉先"先生的分享, 他的博客带我进入了Lucene的大门 :http://www.cnblogs.com/forfuture1978/category ...
- 全文检索技术 Lucene
文章目录 全文检索简介(什么是全文检索) 数据分类 结构化数据搜索 非结构化数据查询方法 全文检索的应用场景 Lucene简介 创建索引库 理论部分(很重要) 创建原始文档 创建文档对象 分析文档 创 ...
- (转)全文检索技术学习(一)——Lucene的介绍
http://blog.csdn.net/yerenyuan_pku/article/details/72582979 本文我将为大家讲解全文检索技术--Lucene,现在这个技术用到的比较多,我觉得 ...
- lucene教程--全文检索技术详解
一 什么是全文检索 1.1 全文检索概念 全文检索是一种将文件中所有文本与检索项匹配的检索方法.它可以根据需要获得全文中有关章.节.段.句.词等信息.计算机程序通过扫描文章中的每一个词,对每一个词建立 ...
- 全文检索工具包Lucene
什么是全文检索 数据的分类 结构化数据:指的是格式固定.长度固定.数据类型固定的数据,例如数据库中的数据. 非结构化数据:指的是格式不固定.长度不固定.数据类型不固定的数据,例如 word 文档.pd ...
- 全文检索(一) -- Lucene
1. 前言 1.1 为什么要用Lucene 原来的方式实现搜索功能,我们的搜索流程如下图:如果用户比较少而且数据库的数据量比较小,那么这种方式实现搜索功能在企业中是比较常见的. 现在的方案(使用Luc ...
- 全文检索框架Lucene——原理
一.总论 根据 http://lucene.apache.org/java/docs/index.html 定义: Lucene 是一个高效的,基于Java 的全文检索库. 所以在了解Lucene之前 ...
- 全文检索工具Lucene入门教程
目录 1.什么是Lucene 1.1什么是全文检索 1.2 全文检索的应用场景 1.3. 如何实现全文检索 2.Lucene实现全文检索的流程 2.1. 创建索引和搜索流程图 2.2. 创建索引 2. ...
- ElasticSearch全文检索技术
目录 数据检索问题 大规模数据如何检索? 传统数据库的应对解决方案? 非关系型数据库的解决方案? 完全把数据放入内存怎么样? 全文检索技术 什么是全文检索? 全文检索场景 实时搜索与传统搜索 Elas ...
- 全文搜索技术—Lucene
1. 内容安排 实现一个文件的搜索功能,通过关键字搜索文件,凡是文件名或文件内容包括关键字的文件都需要找出来.还可以根据中文词语进程查询,并且支持多种条件查询. 本案例中的原始内容就是磁盘上的文件 ...
最新文章
- hive币涨幅空间大吗_空间大、油耗低,家用MPV领域的三款全能好车,你心动了吗?...
- 浅谈caffe中train_val.prototxt和deploy.prototxt文件的区别
- SAP 物料主数据屏幕增强
- 哈希表处理冲突的方法?
- 史上最简单的SpringCloud教程 | 第五篇: 路由网关(zuul)
- pytorch教程龙曲良46-55
- 题库 java_java题库
- 数学建模 非线性规划原理的应用与编程实现
- net.conn read 判断数据读取完毕_高并发:缓存模式以及缓存的数据一致性
- ctf 抓捕赵德汉_2017年网络空间安全技术大赛部分writeup
- unity有用资源的导出未package便于在其他工程用的问题解决
- HTML iframe标签下 子页面调用父页面js 容易产生的跨域调用问题 Uncaught DOMException
- 用友U9 SOA Ready (转载)
- SplitContainer的使用
- 计算机表格快捷键,EXCEL表格所有的快捷键《excel一键到底 快捷键》
- 数据科学和人工智能技术笔记 二十、数据可视化
- 烈日炎炎,向亲爱的爸爸说声辛苦了
- 译 | 如果你惯用右手,你应该把鼠标放在左边的10个理由
- 自制合成孔径雷达(3) doppler代码解读
- SAR舰船数据集----SSDD
热门文章
- 【2018黑龙江省赛】UPC-7222 Overflow(模拟物理水体积)
- 【独行秀才】macOS Big Sur 11.5 Beta3版(20G5042c)原版镜像
- 半实物仿真技术在复杂控制系统研发过程中的典型应用
- android 好友功能,ListView模拟微信好友功能
- A Knee_Guided Evolutionary Algorithm for Compressing Deep Neural Network (KGEA)解读
- 亲测win10安装mac虚拟机+网络配置完整过程
- 第39级台阶 蓝桥杯递归 java
- 批量安装windows系统补丁包
- init mysql db error_Python mysql curs错误
- 论组织管理-EMBA课程小记