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

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

内容简介:Lucene教程--维护索引、查询对象和相关度排序

索引维护

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

说明:更新索引是先删除再添加,建议对更新需求采用此方法并且要保证对已存在的索引执行更新,可以先查询出来,确定更新记录存在执行更新操作。

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

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

查看所有标签

猜你喜欢:

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

实现领域驱动设计

实现领域驱动设计

Vaughn Vernon / 滕云 / 电子工业出版社 / 2014-3 / 99.00元

领域驱动设计(DDD)是教我们如何做好软件的,同时也是教我们如何更好地使用面向对象技术的。它为我们提供了设计软件的全新视角,同时也给开发者留下了一大难题:如何将领域驱动设计付诸实践?Vaughn Vernon 的这本《实现领域驱动设计》为我们给出了全面的解答。 《实现领域驱动设计》分别从战略和战术层面详尽地讨论了如何实现DDD,其中包含了大量的最佳实践、设计准则和对一些问题的折中性讨论。《实......一起来看看 《实现领域驱动设计》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试