内容简介: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); //遍历目录下的文档,创建Document List<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)); //定义IndexReader IndexReader reader = DirectoryReader.open(directory); //创建indexSearcher IndexSearcher 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 查询语法官方介绍:
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); } //向文档中添加Field document.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;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 回归中的相关度和决定系数
- ElasticSearch 揭秘lucene的相关度分数算法
- elasticsearch学习笔记(三十)——Elasticsearch 相关度评分 TF&IDF算法
- elasticsearch学习笔记高级篇(九)——多shard场景下相关度分数不准确问题
- 图形化排序算法比较:快速排序、插入排序、选择排序、冒泡排序
- 排序算法下——桶排序、计数排序和基数排序
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。