Lucene教程--维护索引、查询对象和相关度排序
1 索引维护
1.1 添加索引
步骤:
1)创建存放索引的目录Directory
2)创建索引器配置管理类IndexWriterConfig
3)使用索引目录和配置管理类创建索引器
4)使用索引器将Document写到索引文件中
代码:
// 定义索引存储目录Directory directory = FSDirectory.open(new File(indexFolder));//标准分析器Analyzer standardAnalyzer = new StandardAnalyzer();IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_4_10_3,standardAnalyzer);// 定义索引操作对象IndexWriter indexWriter = new IndexWriter(directory,indexWriterConfig);//遍历目录下的文档,创建DocumentList<Document> docs = IndexUtils.file2Document(indexSource);// 遍历目录 下的文件生成的文档,调用indexWriter方法创建索引for (Document document : docs) {indexWriter.addDocument(document);}// 索引操作流关闭indexWriter.close();
1.2 删除索引
1)删除符合条件的索引
// 索引目录Directory directory = FSDirectory.open(new File(indexFolder));// 定义索引操作对象IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_4_10_3,new StandardAnalyzer()));// 删除索引,文件名称等于“springmvc.txt”的索引删除indexWriter.deleteDocuments(new Term("fileName", "springmvc.txt"));//索引删除后无法恢复indexWriter.commit();// 关闭索引操作流indexWriter.close();
说明:根据Term项删除索引,满足条件的将全部删除,建议参照关系数据库基于主键删除方式,所以在创建索引时需要创建一个主键Field,删除时根据此主键Field删除。
索引删除后将放在Lucene的回收站中,Lucene3.X版本可以恢复删除的文档,3.X之后无法恢复。
2)删除全部索引
// 索引目录Directory directory = FSDirectory.open(new File(indexFolder));// 定义索引操作对象IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_4_10_3,new StandardAnalyzer()));//删除全部索引indexWriter.deleteAll();
说明:将索引目录的索引信息全部删除,直接彻底删除,无法恢复。
1.3 更新索引
// 索引目录Directory directory = FSDirectory.open(new File(indexFolder));// 定义索引操作对象IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_4_10_3,new StandardAnalyzer()));// 创建更新文档Document doc_update = new Document();Field field_fileName = new TextField("fileName", "springmvc.txt",Store.YES);doc_update.add(field_fileName);// 根据条件更新索引,将fileName等于“springmvc_test.txt”的更新为上边的文档// 更新的机制 是先删除再添加,如果原根据fileName没有找到“springmvc_test.txt”,则添加新文档indexWriter.updateDocument(new Term("fileName", "springmvc_test.txt"),doc_update);//提交indexWriter.commit();//关闭indexWriter.close();
说明:更新索引是先删除再添加,建议对更新需求采用此方法并且要保证对已存在的索引执行更新,可以先查询出来,确定更新记录存在执行更新操作。
2 Query和QueryParser
2.1 创建查询的两种方法
创建查询
对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。
可通过两种方法创建查询对象:
1)使用Lucene提供Query子类
Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。
如下代码:
Query query = new TermQuery(new Term("name", "lucene"));
2)使用QueryParse解析查询表达式
QueryParse会将用户输入的查询表达式解析成Query对象实例。
如下代码:
QueryParser queryParser = new QueryParser("name", new IKAnalyzer());Query query = queryParser.parse("name:lucene");
2.2 通过Query 搜索
2.2.1 TermQuery
TermQuery,通过项查询,TermQuery不使用分析器所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。
//创建查询对象Query query = new TermQuery(new Term("fileName", "springmvc_test.txt"));//搜索索引 目录Directory directory = FSDirectory.open(new File(indexFolder));//定义IndexReaderIndexReader reader = DirectoryReader.open(directory);//创建indexSearcherIndexSearcher indexSearcher = new IndexSearcher(reader);//执行搜索TopDocs topDocs = indexSearcher.search(query, 100);
2.2.2 NumericRangeQuery
NumericRangeQuery,指定数字范围查询,如下:
//文件大小在0到1024的文件NumericRangeQuery<Long> numericRangeQuery = NumericRangeQuery.newLongRange("fileSize", 0l, 1024l, true, true);
2.2.3 BooleanQuery
BooleanQuery,布尔查询,实现组合条件查询,如下:
// 数字范围查询NumericRangeQuery<Long> numericRangeQuery = NumericRangeQuery.newLongRange("fileSize", 0l, 1024l, true, true);//定义Boolean查询BooleanQuery booleanQuery = new BooleanQuery();//必须满足fileSize在0到1024范围的条件booleanQuery.add(numericRangeQuery, Occur.MUST);//根据文件名搜索Query query = new TermQuery(new Term("fileName", "springmvc.txt"));//不查询文件名为“springmvc_test.txt”booleanQuery.add(query, Occur.MUST);IndexReader reader = DirectoryReader.open(directory);IndexSearcher searcher = new IndexSearcher(reader);TopDocs topDocs = searcher.search(booleanQuery, 100);
说明:
Occur.MUST 查询条件必须满足,相当于and
Occur.SHOULD 查询条件可选,相当于or
Occur.MUST_NOT 查询条件不能满足,相当于not非
2.2.4 MatchAllDocsQuery
使用MatchAllDocsQuery查询索引目录中的所有文档,如果只存在过滤而没有查询条件时可以使用此类定义Query,如下:
//查询全部文档Query query = new MatchAllDocsQuery();
2.3 通过QueryParser搜索
通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过System.out.println(query);查询。
Lucene查询语法官方介绍:
http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html
2.3.1 QueryParser查询
QueryParser使用方法:
//f是默认搜索的域QueryParser queryParser = new QueryParser("f", analyzer);// 指定查询语法 ,如果不指定fileName就搜索默认的域Query query2 = queryParser.parse("fileName:springmvc.txt");或:Query query2 = queryParser.parse("spring AND web");
上边介绍的基于类的查询方法,使用QueryParser可用下边的查询语法 实现,
项查询:
FieldName : value
范围查询:
FieldName:[min TO max]
注意:QueryParse不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用NumericRangeQuery。
组合查询:
上边BooleanQuery例子的查询表达式如下:
+fileSize:[0 TO 1024] +fileName:springmvc.txt
上边的表达式表示fileSize的大小在0和1024之间且fileName为“springmvc.txt”,必须满足的条件使用+(加号)表示。
与BooleanQuery中Occur对应的符号如下:
Occur.MUST 查询条件必须满足,相当于and |
+(加号) |
Occur.SHOULD 查询条件可选,相当于or |
空(不用符号) |
Occur.MUST_NOT 查询条件不能满足,相当于not非 |
-(减号) |
关键字查询
AND:关键字1 AND 关键字2
两个关键字都匹配上条件满足。
OR:关键字1 OR 关键字2
两个关键字匹配一个条件满足
NOT:关键字1 NOT 关键字2
关键字1满足,关键字2不满足
2.3.2 MultiFieldQueryParser组合域查询
通过MuliFieldQueryParse对多个域查询,比如商品信息查询,输入关键字需要从商品名称和商品内容中查询。
代码:
//设置组合查询域String[] fields = {"fileName","fileContent"};//创建查询解析器QueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());//查询文件名、文件内容中包括“java”关键字的文档Query query = queryParser.parse("java");
3 相关度排序
3.1什么是相关度排序
相关度排序是查询结果按照与查询关键字的相关性进行排序,越相关的越靠前。比如搜索“Lucene”关键字,与该关键字最相关的文章应该排在前边。
3.2 相关度打分
Lucene对查询关键字和索引文档的相关度进行打分,得分高的就排在前边。如何打分呢?Lucene是在用户进行检索时实时根据搜索的关键字计算出来的,分两步:
1)计算出词(Term)的权重
2)根据词的权重值,采用空间向量模型算法计算文档相关度得分。
什么是词的权重?
通过索引部分的学习明确索引的最小单位是一个Term(索引词典中的一个词),搜索也是要从Term中搜索,再根据Term找到文档,Term对文档的重要性称为权重,影响Term权重有两个因素:
Term Frequency (tf):
指此Term在此文档中出现了多少次。tf 越大说明越重要。
词(Term)在文档中出现的次数越多,说明此词(Term)对该文档越重要,如“Lucene”这个词,在文档中出现的次数很多,说明该文档主要就是讲Lucene技术的。
Document Frequency (df)
即有多少文档包含次Term。df 越大说明越不重要。
比如,在一篇英语文档中,this出现的次数更多,就说明越重要吗?不是的,有越多的文档包含此词(Term), 说明此词(Term)太普通,不足以区分这些文档,因而重要性越低。
3.3 设置boost影响打分结果
boost是一个加权值(默认加权值为1.0f),它可以影响权重的计算。
在索引时对某个文档的Field域设置加权值高,在搜索时匹配到这个Field就可能排在前边。
lucene在执行搜索时对某个域进行加权,在进行组合域查询时,匹配到加权值高的域最后计算的相关度得分就高。
3.3.1 索引时设置boost加权值
如果希望某些文档更重要,当此文档中包含所要查询的词则应该得分较高,这样相关度排序可以排在前边,可以在创建索引时设定文档中某些域(Field)的boost值来实现,如果不进行设定,则Field Boost默认为1.0f。一旦设定,除非删除此文档,否则无法改变。
代码:
field. setBoost(XXXf); XXX即权值。
测试:
可以将springmvc.txt的file_content加权值设置为10.0f,结果搜索spring时如果内容可以匹配到关键字就可以把springmvc.txt文件排在前边。
代码:
索引时设置boost加权值:
//设置加权值if(file_name.equals("springmvc.txt")){//设置比默认值 1.0大的field_file_content.setBoost(20.0f);}if(file_name.equals("spring_README.txt")){//设置比默认值 1.0大的field_file_content.setBoost(30.0f);}//向文档中添加Fielddocument.add(field_file_content);
搜索时:
// 设置组合查询域,如果匹配到一个域就返回记录String[] fields = { "file_content" };//设置评分,文件名称中包括关键字的评分高/*Map<String,Float> boosts = new HashMap<String,Float>();boosts.put("file_content", 3.0f);*/// 创建查询解析器QueryParser queryParser = new MultiFieldQueryParser(fields,new StandardAnalyzer());// 查询文件名、文件内容中包括“java”关键字的文档Query query = queryParser.parse("spring");TopDocs topDocs = indexSearcher.search(query, 100);ScoreDoc[] scoreDocs = topDocs.scoreDocs;
结果:
springmvc.txt排在最前边
3.3.2 搜索时设置boost加权值
在执行搜索时对某个域进行加权,在进行组合域查询时,匹配到加权值高的域最后计算的相关度得分就高。通常把标题、书名等域的加权值设置高点。
//设置组合查询域String[] fields = {"file_name","file_content"};//设置评分,文件名称中包括关键字的评分高Map<String,Float> boosts = new HashMap<String,Float>();boosts.put("file_name", 10.0f);//创建查询解析器QueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer(), boosts);//查询文件名、文件内容中包括“springmvc.txt”关键字的文档,由于设置了文件名称域的加权值高,所以名称中匹配到关键字的应该排在前边Query query = queryParser.parse("springmvc.txt");
测试:
搜索springmvc.txt,由于文件名中为springmvc.txt应该让它排在前边,内容中有springmvc.txt应该排在后边。
springmvc.txt:
测试结果它应该排在前边
spring_README.txt
内容中包括springmvc.txt,也能匹配到但要排在后边。
代码:
//设置评分,文件名称中包括关键字的评分高Map<String,Float> boosts = new HashMap<String,Float>();boosts.put("file_name", 30.0f);// 创建查询解析器QueryParser queryParser = new MultiFieldQueryParser(fields,new StandardAnalyzer(),boosts);// 查询文件名、文件内容中包括“java”关键字的文档Query query = queryParser.parse("springmvc.txt");TopDocs topDocs = indexSearcher.search(query, 100);ScoreDoc[] scoreDocs = topDocs.scoreDocs;
Lucene教程--维护索引、查询对象和相关度排序相关推荐
- Lucene 的四大索引查询 ——bool 域搜索 通配符 范围搜索
Lucene 的四大索引查询 清单1:使用布尔操作符 Java代码 //Test boolean operator blic void testOperator(String index ...
- Lucene教程具体解释
注明:本文是由本人在开发有关基于lucene资源检索系统时的一点总结,当中一部分是自己依据开发过程自己总结的,也有部分是摘自网络,因无法获取当时摘文的地址,所以在此没有写源地址. 转载请声明出处 Lu ...
- Lucene教程--入门程序详解
Lucene 入门程序 1 需求 实现一个歌词搜索系统,通过关键字搜索,凡是文件名或文件内容包括关键字的文件都要找出来. 注意:该入门程序只对文本文件(.txt)搜索. 2 开发环境 Jdk:1.7. ...
- lucene教程--全文检索技术详解
一 什么是全文检索 1.1 全文检索概念 全文检索是一种将文件中所有文本与检索项匹配的检索方法.它可以根据需要获得全文中有关章.节.段.句.词等信息.计算机程序通过扫描文章中的每一个词,对每一个词建立 ...
- Lucene教程详解
欢迎关注微信账号:java那些事:csh624366188.每天一篇java相关的文章 注明:本文是由本人在开发有关基于lucene资源检索系统时的一点总结,其中一部分是自己根据开发过程自己总结的,也 ...
- 建立索引lucene_用Lucene建立搜索索引
建立索引lucene 本文是我们名为" Apache Lucene基础知识 "的学院课程的一部分. 在本课程中,您将了解Lucene. 您将了解为什么这样的库很重要,然后了解Luc ...
- 用Lucene建立搜索索引
本文是我们名为" Apache Lucene基础知识 "的学院课程的一部分. 在本课程中,您将了解Lucene. 您将了解为什么这样的库很重要,然后了解Lucene中搜索的工作方式 ...
- Lucene –快速添加索引和搜索功能
什么是Lucene? Apache LuceneTM是完全用Java编写的高性能,功能齐全的文本搜索引擎库. 它是一项适用于几乎所有需要全文搜索的应用程序的技术,尤其是跨平台的应用程序. Lucene ...
- Oracle数据库:oracle数据表格dmp,sql,pde格式导入与导出,视图、序列、索引等对象的导出,oracle完结,后续开启mysql的学习
Oracle数据库:oracle数据表格dmp,sql,pde格式导入与导出,视图.序列.索引等对象的导出,oracle完结,后续开启mysql的学习 2022找工作是学历.能力和运气的超强结合体,遇 ...
最新文章
- spark uniq 本质上就是单词计数
- antd 上传进度_antd vue upload组件使用customRequest上传文件显示文件上传进度
- 华为鸿蒙产业链股票,华为P40或用鸿蒙 华为产业链概念股一览
- C++学习——C++中的四种类型转换
- demo_ajax_json.js,ajax小demo-----ajax中json的使用
- 【操作系统】部分概念解释题
- 阿里 异构数据 mysql_异构数据库迁移
- Javascript技术实现真正的网上试听
- 关于Lua打包cocos2d项目
- eval函数python_Python eval()函数
- 大数据平台技术可以提供哪些服务
- acs712电流检测怎么用_工程师都用这个巧妙廉价的电流检测电路!
- B22-SVN在iOS开发的使用中遇到的问题
- oracle 表或视图不存在
- 六石管理学:头目们为什么要忽略产品质量
- a form 出口享惠情况_进出口报关
- 计算机知识竞赛形式,关于计算机知识竞赛试题
- [CSP-S模拟测试]:赤壁情(DP)
- 分享优秀品牌平面广告创意作品的创意密码
- 甘肃省国家沙漠公园功能区划及分布
热门文章
- C++ 类中的static成员的初始化
- 多重签名(Multisig)
- 百度超级链XChain(2)p2p网络
- java元婴期(29)----java进阶(springmvc(3)---springmvc和mybatis整合参数绑定(上))
- java筑基期(6)----javascript(高级(2))
- TF-A代码阅读: SP_EL3栈内存-cpu_data内存的介绍(cpu_context介绍)
- 基于策略的一种高效内存池的实现
- php 数据显示格式,php数据格式
- Re题目------Enm.exe
- C++使用类静态成员跟踪对象的个数