(四)Lucene——搜索和相关度排序
1. 搜索
1.1 创建查询对象的方式
- 通过Query子类来创建查询对象
Query子类常用的有:TermQuery、NumericRangeQuery、BooleanQuery
特点:不能输入lucene的查询语法,不需要指定分词器
- 通过QueryParser来创建查询对象(常用)
QueryParser、MultiFieldQueryParser
特点:可以输入lucene的查询语法、可以指定分词器
1.2 通过Query子类来创建查询对象
1.2.1 TermQuery(精确的词项查询)
@Test
public void termQuery() {
// 创建TermQuery对象
Query query = new TermQuery(new Term("description", "java"));
doSearch(query);
}
private void doSearch(Query query) {
// 创建IndexSearcher
// 指定索引库的地址
try {
File indexFile = new File("D:\\DBIndex\\");
Directory directory = FSDirectory.open(indexFile);
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
// 通过searcher来搜索索引库
// 第二个参数:指定需要显示的顶部记录的N条
TopDocs topDocs = searcher.search(query, 10);
// 根据查询条件匹配出的记录总数
int count = topDocs.totalHits;
System.out.println("匹配出的记录总数:" + count);
// 根据查询条件匹配出的记录
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
// 获取文档的ID
int docId = scoreDoc.doc;
// 通过ID获取文档
Document doc = searcher.doc(docId);
System.out.println("商品ID:" + doc.get("id"));
System.out.println("商品名称:" + doc.get("name"));
System.out.println("商品价格:" + doc.get("price"));
System.out.println("商品图片地址:" + doc.get("pic"));
System.out.println("==========================");
// System.out.println("商品描述:" + doc.get("description"));
}
// 关闭资源
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
1.2.2 NumericRangeQuery(数字范围查询)
@Test
public void numericRangeQuery() {
// 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query query = NumericRangeQuery.newFloatRange("price", 55f, 60f, true, false);
doSearch(query);
}
1.2.3 BooleanQuery(组合查询)
@Test
public void booleanQuery() {
// 创建BooleanQuery
BooleanQuery query = new BooleanQuery();
// 创建TermQuery对象
Query q1 = new TermQuery(new Term("description", "lucene"));
// 创建NumericRangeQuery对象
// 参数:域的名称、最小值、最大值、是否包含最小值、是否包含最大值
Query q2 = NumericRangeQuery.newFloatRange("price", 55f, 60f, true, false); // 组合关系代表的意思如下:
// 1、MUST和MUST表示“与”的关系,即“交集”。
// 2、MUST和MUST_NOT前者包含后者不包含。
// 3、MUST_NOT和MUST_NOT没意义
// 4、SHOULD与MUST表示MUST,SHOULD失去意义;
// 5、SHOUlD与MUST_NOT相当于MUST与MUST_NOT。
// 6、SHOULD与SHOULD表示“或”的概念。 query.add(q1, Occur.MUST_NOT);
query.add(q2, Occur.MUST_NOT); doSearch(query);
}
1.3 通过QueryParser来创建查询对象
1.3.1 QueryParser
通过QueryParser来创建query对象,可以指定分词器,搜索时的分词器和创建该索引的分词器一定要一致。还可以输入查询语句。
@Test
public void indexSearch() throws Exception {
// 创建query对象
// 使用QueryParser搜索时,需要指定分词器,搜索时的分词器要和索引时的分词器一致
// 第一个参数:默认搜索的域的名称
QueryParser parser = new QueryParser("description", new StandardAnalyzer()); // 通过queryparser来创建query对象
// 参数:输入的lucene的查询语句(关键字一定要大写)
Query query = parser.parse("description:java AND lucene"); doSearch(query);
}
1.3.2 MultiFieldQueryParser(多域查询)
@Test
public void multiFieldQueryParser() throws Exception {
// 创建 MultiFieldQueryParser
// 默认搜索的多个域的域名
String[] fields = { "name", "description" };
Analyzer analyzer = new StandardAnalyzer();
Map<String, Float> boosts = new HashMap<String, Float>();
boosts.put("name", 200f);
MultiFieldQueryParser parser = new MultiFieldQueryParser(fields, analyzer, boosts); // Query query = parser.parse("name:lucene OR description:lucene");
Query query = parser.parse("java");
System.out.println(query); doSearch(query);
}
1.3.3 查询语法
(1)基础的查询语法,关键词查询
域名+“:”+搜索的关键字
例如:content:java
(2)范围查询
域名+“:”+[最小值 TO 最大值]
例如:size:[1 TO 1000]
注意:QueryParser不支持对数字范围的搜索,它支持字符串范围。数字范围搜索建议使用NumericRangeQuery。
(3)组合条件查询
|
Occur.MUST 查询条件必须满足,相当于and |
+(加号) |
|
Occur.SHOULD 查询条件可选,相当于or |
空(不用符号) |
|
Occur.MUST_NOT 查询条件不能满足,相当于not非 |
-(减号) |
(3.1)+条件1 +条件2:两个条件之间是并且的关系and
例如:+filename:apache +content:apache
(3.2)+条件1 条件2:必须满足第一个条件,忽略第二个条件
例如:+filename:apache content:apache
(3.3)条件1 条件2:两个条件满足其一即可。
例如:filename:apache content:apache
(3.4)-条件1 条件2:必须不满足条件1,要满足条件2
例如:-filename:apache content:apache
(4)组合查询(3)的第二种写法
- 条件1 AND 条件2
- 条件1 OR 条件2
- 条件1 NOT 条件2
1.4 TopDocs
Lucene搜索结果可通过TopDocs遍历,TopDocs类提供了少量的属性,如下:
|
方法或属性 |
说明 |
|
totalHits |
匹配搜索条件的总记录数 |
|
scoreDocs |
顶部匹配记录 |
注意:
Search方法需要指定匹配记录数量n:indexSearcher.search(query, n)
TopDocs.totalHits:是匹配索引库中所有记录的数量
TopDocs.scoreDocs:匹配相关度高的前边记录数组,scoreDocs的长度小于等于search方法指定的参数n
2. 相关度排序
2.1 什么是相关度排序
相关度排序就是查询关键字与查询结果的匹配相关度。匹配越高的越靠前。Lucene是通过打分来进行相关度排序的。
2.1.1 打分分两步:
step1:根据词计算词的权重
step2:根据词的权重进行打分
2.1.2 词的权重
词指的就是term。也就是说一个term对一个文档的重要性,就叫词的权重。
影响词的权重的方式有两种:
- Tf ——词在同一个文档中出现的频率
Tf越高,说明词的权重越高
- Df ——词在多个文档中出现的频率
Df越高,说明词的权重越低
以上是自然打分的规则。
2.2 设置boost值影响打分
Boost:加权值,默认是1.0f。
设置加权值可以在创建索引时(如下代码)设置,也可以在查询时(见1.3.2 MultiFieldQueryParser(多域查询))设置。
for (Book book : list) {
document = new Document();
// store:如果是yes,则说明存储到文档域中
// 图书ID
// 不分词、索引、存储 StringField
Field id = new StringField("id", book.getId().toString(), Store.YES);
// 图书名称
// 分词、索引、存储 TextField
Field name = new TextField("name", book.getName(), Store.YES);
············
// 设置boost值
if (book.getId() == 4)
description.setBoost(100f);
// 将field域设置到Document对象中
document.add(id);
·············
}
Boost值是设置到Field域上的。
(四)Lucene——搜索和相关度排序的更多相关文章
- Lucene 08 - 什么是Lucene的相关度排序 + Java API调整相关度
目录 1 什么是相关度 2 相关度评分 3 相关度设置 3.1 更改相关度的需求 3.2 实现需求-设置广告 1 什么是相关度 概念: 相关度指两个事物之间的关联关系(相关性). Lucene中指的是 ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(三)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(三) Lucene有表达式就有运算符,而运算符使用起来确实很方便,但另外一个问题来了. 代码 4.3.4.1 Analyzer anal ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(二)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(二) 4.3 表达式用户搜索,只会输入一个或几个词,也可能是一句话.输入的语句是如何变成搜索条件的上一篇已经略有提及. 4.3.1 观察 ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(一)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(一) 既然是内容筛选,或者说是搜索引擎,有索引,必然要有搜索.搜索虽然与索引有关,那也只是与索引后的文件有关,和索引的程序是无关的,因此 ...
- Lucene搜索方式大合集
package junit; import java.io.File; import java.io.IOException; import java.text.ParseException; imp ...
- lucene 搜索demo
package com.ljq.utils; import java.io.File; import java.util.ArrayList; import java.util.List; impor ...
- Lucene学习总结之七:Lucene搜索过程解析
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
- Lucene系列六:Lucene搜索详解(Lucene搜索流程详解、搜索核心API详解、基本查询详解、QueryParser详解)
一.搜索流程详解 1. 先看一下Lucene的架构图 由图可知搜索的过程如下: 用户输入搜索的关键字.对关键字进行分词.根据分词结果去索引库里面找到对应的文章id.根据文章id找到对应的文章 2. L ...
- Lucene学习总结之七:Lucene搜索过程解析 2014-06-25 14:23 863人阅读 评论(1) 收藏
一.Lucene搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
随机推荐
- [BZOJ5248][九省联考2018]一双木棋(连通性DP,对抗搜索)
5248: [2018多省省队联测]一双木棋 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 43 Solved: 34[Submit][Status ...
- JZYZOJ1372 [noi2002]荒岛野人 扩展欧几里得
http://172.20.6.3/Problem_Show.asp?id=1372 想法其实很好想,但是我扩展欧几里得还是用得不熟练,几乎是硬套模板,大概因为今天一个下午状态都不大好.扩展欧几里得算 ...
- bzoj 3900: 交换茸角
3900: 交换茸角 Description 动物园里有 n 头麋鹿.每头麋鹿有两支茸角,每支茸角有一个重量.然而,一旦某头麋鹿上 两支茸角的重量之差过大,这头麋鹿就会失去平衡摔倒.为了不然这种悲剧发 ...
- 基于socket的udp传输,socketserver模块,进程
基于UDP的套接字 udp是无连接的,先启动哪一端都不会报错 socket.SOCK_DGRAM 数据报协议 udp不会发送空数据,什么都不输入直接发送也会有报头发过去 服务端 import sock ...
- 找出最小元素的下标 Exercise07_10
import java.util.Scanner; /** * @author 冰樱梦 * 时间:2018年下半年 * 题目:找出最小元素的下标 * */ public class Exercise0 ...
- Git 对比 SVN
转自:http://www.aqee.net/5-fundamental-differences-between-git-svn/ 我是一开始就用Mercurial, Git这类的系统.(现在已经百分 ...
- mybatis批量操作-xml方式
在实际项目中,我们一般都会用到批量insert.delete.update等操作,由于使用频率还是蛮高的,这里就做个简单的记录,供以后学习和参考. 批量insert 在数据库中,批量插入可以是多条in ...
- python升级导致yum命令无法使用的解决办法?
yum是依赖特定的python版本的,不同的linux系统需要的python版本不同. 查看yum的启动脚本:which is yum 头一行指定使用的python版本,这个必须是系统需要的,而不要使 ...
- synchronized 线程同步
synchronized 通常用来形容一次方法的调用,调用一旦开始,调用者必须等到方法调用返回后,才能继续执行后续的操作. 1.demo package demo1; public class My ...
- iOS: 状态栏、导航栏、标签栏、工具栏
三种项目栏总结: 工具栏:UIToolBar 导航栏:UINavigationBar 标签栏:UITabBar UIToolBar的按钮单元为:UIBarButtonItem UINavigati ...