Lucene 搜索功能
搜索过程
图解:
主要 API:
- IndexSearcher: //所有搜索都通过 IndexSearcher 进行,他们将调用该类中重载的 search() 方法
- Query: //封装某种查询类型的具体子类,Query 实例将会被传递给 IndexSearcher 的 search() 方法
- QueryParser: //将用户输入的查询表达式处理成各种具体的 Query 对象
- TopDocs: //保存由 IndexSearcher.search() 方法返回的具有较高评分的文档
- ScoreDoc: //提供对 TopDocs 中每条搜索结果的访问接口
下面,将对这几类 API 做分别的讨论。
使用IndexSearcher类
// 创建 IndexSearcher 类实例:
Directory dir = FSDirectory.open(/path/to/indices);
IndexReader reader = IndexReader.open(dir);
IndexSearcher searcher = new IndexSearcher(reader);
// 实现搜索功能 IndexSearcher.search():
TopDocs search(Query query, int n) //————直接进行搜索,返回评分最高的N个文档
TopDocs search(Query query, Filter filter, int n) //————搜索受文档子集约束,约束条件基于过滤条件
TopFieldDocs search(Query query, Filter filter, int n, Sort sort) //————排序
void search(Query query, Collector results) //————使用自定义文档访问策略
void search(Query query, Filter filter, Collector results)
使用TopDocs类
调用 IndexSearcher.search() 方法,返回 TopDocs 对象。
TopDocs.totalHits() //匹配搜索条件的文档数量
TopDocs.scoreDocs() //包含搜索结果的ScoreDoc对象数组
TopDocs.getMaxScore() //如果已完成排序这返回最大评分
使用 Query 类
使用 Query 类就是直接使用 Lucene 的各种 Query API 来进行查询。
Query 的子类可以直接实例化,也可以通过 QueryParser 类实例化。通过 QueryParser 实例化会首先将自由文本转换为各种 Query 类型,这个将在【使用 QueryParser 类】 小节讲述。
TermQuery:
该查询是区分大小写的,搜索前要对索引后的项大小写进行匹配
TermQuery:
//该查询是区分大小写的,搜索前要对索引后的项大小写进行匹配
Term t = new Term("contents", "java");
Query query = new TermQuery(t);
TermRangeQuery:
索引中的各个 Term 回想会按照字典编排排序,并允许在 Lucene 的 TermQuery 对象提供的范围内进行文本项的直接搜索。
用两个Boolean对象参数表示是否包含搜索范围的起点/终点。
TermRangeQuery:
//用两个Boolean对象参数表示是否包含搜索范围的起点/终点
TermRangeQuery query = new TermRangeQuery("title2", "d", "j", true, true); //搜索 title 域起始字母从 'd' 到 'j' 的文档
NumericRangeQuery:
用两个Boolean对象参数表示是否包含搜索范围的起点/终点。
NumericRangeQuery:
//用两个Boolean对象参数表示是否包含搜索范围的起点/终点
NumericRangeQuery query = new NumericRangeQuery.newIntRange("pubmonth", 200605, 200609, true, true);
PrefixQuery:
搜索包含以指定字符串开头的项的文档。
PrefixQuery:
//搜索包含以指定字符串开头的项的文档
Term term = new Term("category", "/technology/computers/programing");
PrefixQuery query = new PrefixQuery(term); //搜索编程方面的书籍,包括他们的子类书籍(子目录)
Query query = new TermQuery(term); //搜索编程方面的书籍,不包括子类书籍(子目录)
BooleanQuery:
通过BooleanQuery可以将各种查询类型组合起来。
BooleanQuery:
//通过BooleanQuery可以将各种查询类型组合起来
TermQuery searchingBooks = new TermQuery(new Term("subject", "search"));
Query books2010 = NumericRangeQuery.newIntRange("pubmonth", 201001, 201009, true,true);
BooleanQuery searchingBooks2010 = new BooleanQuery(); searchingBooks2010.add(searchingBooks, BooleanClause.Occur.MUST);
searchingBooks2010.add(books2010,BooleanClause.Occur.MUST)
PhraseQuery:
PhraseQuery类会根据项的位置信息定位某个距离范围内的项所对应的文档。
PhraseQuery:
//PhraseQuery类会根据项的位置信息定位某个距离范围内的项所对应的文档
PhraseQuery query = new PhraseQuery();
query.setSlop(slop);
WildcardQuery:
使用不完整的、缺少某些字母的项进行查询。
WildcardQuery:
//使用不完整的、缺少某些字母的项进行查询
Query query = new WildcardQuery(new Term("contents", "?ild*"));
FuzzyQuery:
用于查询与指定项相似的项(如:three/tree编辑距离为1)。
FuzzyQuery:
//用于查询与指定项相似的项(three/tree编辑距离为1)
Query query = new FuzzyQuery(new Term("contents", "wuzza"));
MatchAllDocsQuery:
MatchAllDocsQuery:
Query query = new MatchAllDocsQuery(); //对匹配的分配固定的评分
Query query = new MatchAllDocsQuery(field); //文档根据指定的域评分
使用 QueryParser 类
QueryParser 对象初始化
与 matchVersion、一个域名和一个分析器一起用于将输入的文本分割成 Terms 对象:
QueryParser parse = new QueryParser(Version.LUCENE_30, "contents", new SimpleAnalzer());
QueryParser 应用示例
IndexSearcher searcher = new IndexSearcher(dir);
QueryParser parse = new QueryParser(Version.LUCENE_30,"contents", new SimpleAnalzer());
Query query = parser.parse("+JUNIT +ANT -MOCK"); //解析 "+JUNIT +ANT -MOCK" 为Query对象
TopDocs docs = searcher.search(query, 10);
QueryParser 解析表达式
1. Query.toString:
- 当查询表达式被解析为后会发生变化,通过 toString 方法可以查看解析后的语句。
//toString:
query.add(new FuzzyQuery(new Term("field", "kountry")), BooleanClause.Occur.MUST);
assertEquals("+kountry~0.5" query.toString(field));
2. 项查询:
- 默认情况下,如果单个词不被识别为更长的其他查询类型表达式的一部分,那么将会被解析为 TermQuery 对象。
//TermQuery
QueryParse parser = new QueryParser(Version.LUCENE_30, "subject", analyzer);
Query query = parser.parse("computers"); //默认域
System.out.printfln("term: " + query);
//输出 term: subject:computers
3. 项范围查询:
- 针对 "文本" 或 "日期" 的范围查询通过括号形式表示,并且只需要在查询范围两端的项之间用 TO(大写)进行连接就可以。
- 用中括号:[] 表示搜索范围包含在内
- 用大括号:{} 表示搜索范围排除在外
- 这里和编程构建 TermRangeQuery 或 NumericRangeQuery 不同,搜索范围不能同时进行包含和排除,只能要么全部包含,要么全部排除。
//项范围查询
QueryParse parser = new QueryParser(Version.LUCENE_30, "subject", analyzer);
Query query = parser.parse("title2:[Q TO V]");
assertTrue(query instanceof TermRangeQuery); Query query = parser.parse("title2:{Q TO \"Tapestry in action\"}");
4. 短语查询:
- 查询语句中庸双引号括起来的项会被转换为 PhraseQuery 对象。在引号里面使用 "通配符" 将不会生效。
- 单项短语对象将会被转换为 TermQuery 对象。
//短语查询
QueryParse parser = new QueryParser(Version.LUCENE_30, "field", new StandardAnalyzer(Version.LUCENE_30));
Query q = parser.parse("\"This is Some Phrase*\"");
assertEquals("analyzed", "\"? ? Some Phrase\"", q.toString("field")) QueryParse parser = new QueryParser(Version.LUCENE_30, "field", analyzer);
Query q = parser.parse("\"term\"");
assertTrue("reduced to TermQuery", q instanceof TermQuery);
5. 布尔操作符:
- 可以使用 AND、OR和NOT,布尔操作符必须全部大写。项之间如果没有指定布尔操作符,默认为 "OR"。
- a AND b 快捷语法 +a +b
- a OR b 快捷语法 ab
- a AND NOT b 快捷语法 +a -b
//布尔操作符
QueryParse parser = new QueryParser(Version.LUCENE_30, "contents", analyzer);
parser.setDefaultOperator(QueryParser.AND_OPERATOR);
6. 前缀查询和通配符查询:
- 如果某项中包含一个星号或者问好,该项会被看作是通配符查询对象 WildcardQuery。
- 当查询只在末尾有一个星号时候,QueryParse 类会将它优化为前缀查询。
- 不管是前缀还是通配符查询,其对象都会被转换为小写字母形式(可控)。
//前缀和通配符查询
QueryParse parser = new QueryParser(Version.LUCENE_30, "filed", analyzer);
Query query = parser.parse("prefixQuery*");
assertEquals("lowercased", "prefixQuery*", q.toString("field"))
7. 数值范围搜索和日期范围搜索:
- QueryParser 类不会建立 NumericRangeQuery 类。
8. 模糊查询:
QueryParse parser = new QueryParser(Version.LUCENE_30, "subject", analyzer);
Query q = parser.parse("kountry~");
System.out.printfln("fuzzy: " + query);
// fuzzy: subject:kountry~0.5
query = parser.parse("kountry~0-7");
System.out.printfln("fuzzy 2: " + query);
// fuzzy: subject:kountry~0.7
9. MatchAllDocsQuery:
- 当输入*:*后会被分析为 MatchAllDocsQuery
10. 分组查询:
- QueryParser 使用分组后的文本类型的查询表达式来支持嵌套 。
//QueryParser 使用分组后的文本类型的查询表达式来支持嵌套 BooleanQuery 子句查询
QueryParse parser = new QueryParser(Version.LUCENE_30, "subject", analyzer);
Query q = parser.parse("(agile OR extreme) AND methodology");
11. 域选择:
- 默认域名是在创建 QueryParser 时候创建。
- 如果使用域选择器表示法,可以对非默认域中的项进行指定。
12. 对子查询设置加权:
- 在浮点数前面加上一个^符号可以对查询进行加权因子设置。
- junit^2.0 testing 会将 junit TermQuery 的加权系数设置为2.0;并维持 testing TermQuery 为默认1.0。
java //————默认域包括 java 项的文档
java junit //————默认域包括 java 和 junit 中一个或两个项的文档
java OR junit //————默认域包括 java 和 junit 中一个或两个项的文档
+java +junit //————默认域包括 java 和 junit 两项的文档
title:java //————title 域中包含 ant 项的文档
title:extreme -subject:sports //————title 域中包含 extreme 且 subject 域中不包含 sports 的文档
tielt:extreme AND NOT subject:sports //————title 域中包含 extreme 且 subject 域中不包含 sports 的文档
(agile OR extreme) AND methodogy //————默认域中包含 methodogy 且包含 agile 和 extreme 中一个或两个的文档
title:"junit in action" //————title 域为 junit in action 的文档
title:"junit action" -5 //————title 域中junit 和 action之 间距离小于5的文档
java* //————包含由 java 开头的文档
java- //————包含与单词 java 相近的单词
lastmodified:[1/1/09 TO 12/31/09] //————lastmodified 域值在这个时间区间的文档
QueryParser 特殊字符
QueryParse 在各个项中使用反斜杠来表示转义,需要转义的字符有:
\
+
-
!
(
)
:
^
]
{
}
_
*
?
搜索结果分页
将首次搜索获得的多页结果手机起来保存在 ScoreDocs 和 IndexSearcher 实例中。
每次用户换页浏览时候都重新进行查询操作
近实时搜索
使用一个打开的 IndexWriter 快速搜索索引的变更内容,而不必首先关闭 writer 或向该 writer 提交。
Lucene 搜索功能的更多相关文章
- 【Lucene3.6.2入门系列】第03节_简述Lucene中常见的搜索功能
package com.jadyer.lucene; import java.io.File; import java.io.IOException; import java.text.SimpleD ...
- Lucene5.5.4入门以及基于Lucene实现博客搜索功能
前言 一直以来个人博客的搜索功能很蹩脚,只是自己简单用数据库的like %keyword%来实现的,所以导致经常搜不到想要找的内容,而且高亮显示.摘要截取等也不好实现,所以决定采用Lucene改写博客 ...
- 如何使用 Lucene 做网站高亮搜索功能?
现在基本上所有网站都支持搜索功能,现在搜索的工具有很多,比如Solr.Elasticsearch,它们都是基于 Lucene 实现的,各有各的使用场景.Lucene 比较灵活,中小型项目中使用的比较多 ...
- 【Lucene】Apache Lucene全文检索引擎架构之搜索功能3
上一节主要总结了一下Lucene是如何构建索引的,这一节简单总结一下Lucene中的搜索功能.主要分为几个部分,对特定项的搜索:查询表达式QueryParser的使用:指定数字范围内搜索:指定字符串开 ...
- 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搜索方式(query类型)
Lucene有多种搜索方式,可以根据需要选择不同的方式. 1.词条搜索(单个关键字查找) 主要对象是TermQuery 调用方式如下: Term term=new Term(字段名,搜索关键字);Qu ...
- lucene3.6笔记添加搜索功能
lucene为程序添加搜索功能,此功能基于已创建好的文档的索引之上.这里我已经为一些文档建立了索引,并保存到硬盘上.下面开始针对这些索引,添加搜索功能. 1.简单的TermQuery搜索 Java代码 ...
- Lucene核心--构建Lucene搜索(上篇,理论篇)
2.1构建Lucene搜索 2.1.1 Lucene内容模型 一个文档(document)就是Lucene建立索引和搜索的原子单元,它由一个或者多个字段(field)组成,字段才是Lucene的真实内 ...
随机推荐
- win7安装gevent时报错 whl is not a supported wheel on this platform.
1.首先强烈推荐一个站点 在使用pip安装python协程包gevent时,需要很多依赖,很多需要编译的底层支持等等,不能拿来就用.总之很多麻烦的事儿. 这个强烈推荐一个站点,里面都是一些编译好的py ...
- 解决session失效之后登陆后重新返回之前的页面
在全局拦截器设置保存之前的url存入session中 登陆之后的地址再重session中存 request只用作一次请求 如果页面跳转几次的话原来的url就不存在了建议存在session @Overr ...
- Deep learning:三十四(用NN实现数据的降维)
数据降维的重要性就不必说了,而用NN(神经网络)来对数据进行大量的降维是从2006开始的,这起源于2006年science上的一篇文章:reducing the dimensionality of d ...
- android NDK 实用学习(一)-获取java端类及其类变量
近期为android 端项目包装一些c++代码,故学习ndk相关知识,现总结如下: 1,java与c++类型参照图: 2,此测试中使用的java类: package com.dasea.test.co ...
- 【转】SQL中Group By的使用
1.概述 2.原始表 3.简单Group By 4.Group By 和 Order By 5.Group By中Select指定的字段限制 6.Group By All 7.Group By与聚合函 ...
- python 继承和多态
在OOP程序设计中,当我们定义一个class的时候,可以从某个现有的class继承,新的class称为子类(Subclass),而被继承的class称为基类.父类或超类(Base class.Supe ...
- soliworks三维机柜布局(四)进入solidworks中三维布线
首先需要在solidworks electrical中创建solidworks装配体文件. 菜单栏:处理--solidworks机柜布局--勾选要创建的装配体--点击确定 在文件列表下右键装配体文件- ...
- whu 1464 deal with numbers
WHU 1464 deal with numbers 题意: 给你一串数字,对着串数字有三项操作: Minus a,b,c:对区间[a,b]总的每个数都减c. Division a,b,c:对区间[ ...
- java实现生产者消费者问题
引言 生产者和消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一个存储空间,如下图所示,生产者向空间里存放数据,而消费者取用数据,如果不加以协调可能会出现以下情况: 生产者消费者图 ...
- 使用 Windows 窗体 TextBox 控件创建密码文本框
密码框是一种 Windows 窗体文本框,它在用户键入字符串时显示占位符. 创建密码文本框 将 TextBox 控件的 PasswordChar 属性设置为某个特定字符. PasswordChar 属 ...