(四)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搜索过程总论 搜索的过程总的来说就是将词典及倒排表信息从索引中读出来,根据用户输入的查询语句合并倒排表,得到结果文档集并对文档进行打分的过程. 其可用如下图示: 总共包括以下几个过程: ...
随机推荐
- 【构造】Gym - 101411F - Figure ans Spots
在最外围的一圈没有意义,所以全都涂黑,内部贪心地涂成棋盘即可. #include<cstdio> #include<cstring> using namespace std; ...
- [JZOJ3484]密码
题目大意: 给你一个很长的字符串a(|a|<=300000),一个比较短的字符串b(|b|<=200),请你搞一些破坏. 你可以从a的两边去掉一些字符使得b仍是a的一个字串,问有多少种方案 ...
- JS小游戏寻找房祖名
提示:1:先把两个图片放到重命名并放到相应的路径内. 2:本小游戏只为闲事练手,如有小bug自行解决,解决不了的可以留言,我看到后解决. 代码如下: <!DOCTYPE html>< ...
- javascript实现原生ajax
自从javascript有了各种框架之后,比如jquery,使用ajax已经变的相当简单了.但有时候为了追求简洁,可能项目中不需要加载jquery这种庞大的js插件.但又要使用到ajax这种功能该如何 ...
- svn: None of the environment variables SVN_EDITOR...问题解决
转:http://blog.163.com/lgh_2002/blog/static/44017526201046111856208/ 问题1: svn: Could not use external ...
- postgres10配置huge_pages
操作系统 修改/boot/grub2/grub.cfg 定位到第一个'menuentry 'CentOS Linux',在"linux16 /vmlinuz"最后面添加 numa= ...
- xpages开发的bom管理系统
domino对流程设计是方便的.假设制作复杂逻辑的应用就难了.可是还是能够实现的,曾经的一个bom管理系统.刚開始想使用java的ssh来做,后来为了统一平台.还是使用domino来做,经过长时间的研 ...
- [转] SQL SERVER拼接字符串(字符串中有变量)
本文转自:http://blog.csdn.net/sikaiyuan2008/article/details/7848926 SQL SERVER拼接字符串(字符串中有变量)对我来说是一个难点,总是 ...
- iOS:关于UIView切角的两种实现方式
转载自:http://www.jianshu.com/p/451b7fa94e2a 第一种: 我想你一见到代码,就瞬间有吐的冲动,最常用的一种方式... UIButton *button = [[UI ...
- WebService基于SoapHeader实现安全认证[webservice][.net][安全][soapheader]
摘 自: http://blog.sina.com.cn/s/blog_72b7a82d0100yyp8.html WebService基于SoapHeader实现安全认证[webservice][. ...