Lucene教程--维护索引、查询对象和相关度排序

栏目: 编程工具 · 发布时间: 9年前

内容简介: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 查询语法官方介绍:

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);

}

 

//向文档中添加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;

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

深入理解Java虚拟机

深入理解Java虚拟机

周志明 / 机械工业出版社 / 2011-6 / 69.00元

《深入理解Java虚拟机:JVM高级特性与最佳实践》内容简介:作为一位Java程序员,你是否也曾经想深入理解Java虚拟机,但是却被它的复杂和深奥拒之门外?没关系,本书极尽化繁为简之妙,能带领你在轻松中领略Java虚拟机的奥秘。本书是近年来国内出版的唯一一本与Java虚拟机相关的专著,也是唯一一本同时从核心理论和实际运用这两个角度去探讨Java虚拟机的著作,不仅理论分析得透彻,而且书中包含的典型案......一起来看看 《深入理解Java虚拟机》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

MD5 加密
MD5 加密

MD5 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具