文章目录

  • 搜索API详解
    • IndexReader 索引读取器
    • IndexSearch 索引搜索器
    • 查询结果
  • 基本查询详解
    • TermQuery 词项查询
    • BooleanQuery 布尔查询
    • PhraseQuery 短语查询
    • MultiPhraseQuery 多重短语查询
    • SpanNearQuery 临近查询(跨度查询)
    • TermRangeQuery 词项范围查询
    • PrefixQuery, WildcardQuery, RegexpQuery
    • FuzzyQuery 模糊查询
    • 数值查询
  • QuerParser查询解析器
    • QueryParser 传统解析器
    • MultiFieldQueryParser 传统解析器
    • StandardQueryParser 新标准解析器
    • 查询解析语法
  • 总结

如果对Lucene不熟悉的,请移步:Lucene搜索引擎-分词器


当分词、索引存储完毕,就可以开始进行搜索了。

先看一段代码:

public class SearchBaseFlow {public static void main(String[] args) throws IOException, ParseException {// 使用的分词器Analyzer analyzer = new IKAnalyzer4Lucene7(true);// 索引存储目录Directory directory = FSDirectory.open(Paths.get("f:/test/indextest"));// 索引读取器IndexReader indexReader = DirectoryReader.open(directory);// 索引搜索器IndexSearcher indexSearcher = new IndexSearcher(indexReader);// 要搜索的字段String filedName = "name";// 查询生成器(解析输入生成Query查询对象)QueryParser parser = new QueryParser(filedName, analyzer);// 通过parse解析输入(分词),生成query对象Query query = parser.parse("Thinkpad");// 搜索,得到TopN的结果(结果中有命中总数,topN的scoreDocs(评分文档(文档id,评分)))TopDocs topDocs = indexSearcher.search(query, 10);   //前10条//获得总命中数System.out.println(topDocs.totalHits);// 遍历topN结果的scoreDocs,取出文档id对应的文档信息for (ScoreDoc sdoc : topDocs.scoreDocs) {// 根据文档id取存储的文档Document hitDoc = indexSearcher.doc(sdoc.doc);// 取文档的字段System.out.println(hitDoc.get(filedName));}// 使用完毕,关闭、释放资源indexReader.close();directory.close();}
}

搜索的核心API:

搜索API详解

IndexReader 索引读取器

open一个读取器,读取的是该时刻点的索引视图。如果后续索引发生改变,需重新open一个读取器。

获得索引读取器的方式:

  • DirectoryReader.open(IndexWriter indexWriter) 优先使用
  • DirectoryReader.open(Directory)
  • DirectoryReader.openIfChanged(DirectoryReader) 共享当前reader资源重新打开一个(当索引变化时)

IndexReader分为两类:

  • 叶子读取器:支持获取stored fields, doc values, terms(词项), and postings (词项对应的文档)
  • 复合读取器:多个读取器的复合,只可直接用它获取stored fields 。在内部通过CompositeReader.getSequentialSubReaders 得到里面的叶子读取器来获取其他数据

上述代码使用到的DirectoryReader 是 复合读取器。

注意:IndexReader是线程安全的


IndexReader主要API:

LeafReader主要API:

IndexSearch 索引搜索器

应用通过调用它的search(Query,int)重载方法在一个IndexReader上实现搜索。

出于性能的考虑,请使用一个IndexSearcher实例,除非索引发生变化。如索引更新了则通过DirectoryReader.openIfChanged(DirectoryReader) 取得新的读取器,再创建新的搜索器。

注意:IndexSearch是线程安全的

查询结果

基本查询详解

常用的查询API如下:

TermQuery 词项查询

词项查询,最基本、最常用的查询,用来查询指定字段包含指定词项的文档。

TermQuery tq = new TermQuery(new Term("fieldName", "term"));
TermQuery tq = new TermQuery(new Term(“name", “thinkpad"));

BooleanQuery 布尔查询

搜索的条件往往是多个的,如要查询名称包含"电脑" 或 "thinkpad"的商品,就需要两个词项查询做或合并。

布尔查询就是用来组合多个子查询的。每个子查询称为布尔字句 BooleanClause,布尔字句自身也可以是组合的。

组合关系支持如下四种:

  • Occur.SHOULD:或
  • Occur.MUST:且
  • Occur.MUST_NOT:且非
  • Occur.FILTER:同MUST,但该字句不参与评分

布尔查询默认的最大字句数为1024,在将通配符查询这样的查询rewriter为布尔查询时,往往会产生很多的字句,可能抛出TooManyClauses 异常。可通过BooleanQuery.setMaxClauseCount(int)设置最大字句数。

// 布尔查询
Query query1 = new TermQuery(new Term(filedName, "thinkpad"));
Query query2 = new TermQuery(new Term("simpleIntro", "英特尔"));
BooleanQuery.Builder booleanQueryBuilder = new BooleanQuery.Builder();
booleanQueryBuilder.add(query1, Occur.SHOULD);
booleanQueryBuilder.add(query2, Occur.MUST);
BooleanQuery booleanQuery = booleanQueryBuilder.build();// 可像下一行这样写
// BooleanQuery booleanQuery = new BooleanQuery.Builder()
//  .add(query1, Occur.SHOULD).add(query2, Occur.MUST).build();

PhraseQuery 短语查询

最常用的查询,匹配特点序列的多个词项。

PhraserQuery使用一个位置移动因子(slop)来决定任意两个词项的位置(词项出现的次序)可最大移动多少个位置来进行匹配,默认为0。有两种方式来构建对象:

  • 直接用构造方法
  • 用里面的Builder来构建


注意:

  • Builder方式构造中的int 值为词项的位置,后面加入的词项的位置需>=前一词项的位置
  • 所有加入的词项都匹配才算匹配(即使是你在同一位置加入多个词项)
  • 如果需要在同一位置匹配多个同义词中的一个,适合用MultiPhraseQuery

短语查询示例:

PhraseQuery phraseQuery1 = new PhraseQuery("name", "thinkpad", "carbon");
PhraseQuery phraseQuery2 = new PhraseQuery(1, "name", "thinkpad", "carbon");
PhraseQuery phraseQuery3 = new PhraseQuery("name", "笔记本电脑", "联想");
PhraseQuery phraseQuery4 = new PhraseQuery.Builder().add(new Term("name", "笔记本电脑"), 4).add(new Term("name", "联想"), 5).build();
PhraseQuery phraseQuery5 = new PhraseQuery.Builder().add(new Term("name", "笔记本电脑"), 0).add(new Term("name", "联想"), 1).build();

移动因子slop说明:slop是指两个项的位置之间允许的最大间隔距离。

  • String name = “ThinkPad X1 Carbon 20KH0009CD/25CD 超极本轻薄笔记本电脑联想”;
  • 如果想用 thinkpad carbon 来匹配 name,则需要如何移动才会和name中的ThinkPand [X1] Carbon匹配呢?这种情况比较简单,只要计算两者间的距离,thinkpad向左移动1即可,此时slop=1
  • 如果想用 *carbon thinkpad 来匹配 name,则只需要将carbon向右移动3位即可匹配ThinkPand [X1] Carbon,因此slop=3

MultiPhraseQuery 多重短语查询

短语查询的一种更通用的用法,支持同位置多个词的OR匹配。通过里面的Builder来构建MultiPhraseQuery

示例:

// 多重短语查询
Term[] terms = new Term[2];
terms[0] = new Term("name", "笔记本");
terms[1] = new Term("name", "笔记本电脑");
Term t = new Term("name", "联想");
MultiPhraseQuery multiPhraseQuery = new MultiPhraseQuery.Builder().add(terms).add(t).build();// 对比 PhraseQuery在同位置加入多个词 ,同位置的多个词都需匹配,所以查不出
PhraseQuery pquery = new PhraseQuery.Builder().add(terms[0], 0).add(terms[1], 0).add(t, 1).build();

SpanNearQuery 临近查询(跨度查询)

用于更复杂的短语查询,可以指定词间位置的最大间隔跨度。

通过组合一系列的SpanQuery 实例来进行查询,可以指定是否按顺序匹配、slop、gap。

示例:

// SpanNearQuery 临近查询
SpanTermQuery tq1 = new SpanTermQuery(new Term("name", "thinkpad"));
SpanTermQuery tq2 = new SpanTermQuery(new Term("name", "carbon"));
SpanNearQuery spanNearQuery = new SpanNearQuery(new SpanQuery[] { tq1, tq2 }, 1, true);// SpanNearQuery 临近查询 gap slop 使用
SpanNearQuery.Builder spanNearQueryBuilder = SpanNearQuery.newOrderedNearQuery("name");
spanNearQueryBuilder.addClause(tq1).addGap(0).setSlop(1).addClause(tq2);
SpanNearQuery spanNearQuery5 = spanNearQueryBuilder.build();

TermRangeQuery 词项范围查询

用于查询包含某个范围内的词项的文档,如以字母开头a到c的词项。词项在反向索引中是排序的,只需指定的开始词项、结束词项,就可以查询该范围的词项。

如果是做数值的范围查询则用 PointRangeQuery

参数说明:

  • field:字段
  • lowerTerm:下边界词
  • upperTerm:上边界词
  • includeLower:是否包含下边界
  • includeUpper:是否包含上边界

示例:

// TermRangeQuery 词项范围查询
TermRangeQuery termRangeQuery = TermRangeQuery.newStringRange("name", "carbon", "张三", false, true);

PrefixQuery, WildcardQuery, RegexpQuery

  • PrefixQuery 前缀查询
    查询包含以xxx为前缀的词项的文档,是通配符查询,如 app,实际是 app*
  • WildcardQuery 通配符查询
    *表示0个或多个字符,?表示1个字符,\是转义符。通配符查询可能会比较慢,不可以通配符开头(那样就是所有词项了)
  • RegexpQuery 正则表达式查询
    词项符合某正则表达式

这三种查询可能会比较慢,使用时要谨慎

示例:

// PrefixQuery 前缀查询
PrefixQuery prefixQuery = new PrefixQuery(new Term("name", "think"));// WildcardQuery 通配符查询
WildcardQuery wildcardQuery = new WildcardQuery(new Term("name", "think*"));// WildcardQuery 通配符查询
WildcardQuery wildcardQuery2 = new WildcardQuery(new Term("name", "厉害了???"));// RegexpQuery 正则表达式查询
RegexpQuery regexpQuery = new RegexpQuery(new Term("name", "厉害.{4}"));

FuzzyQuery 模糊查询

简单地与索引词项进行相近匹配,允许最大2个不同字符。常用于拼写错误的容错:如把 “thinkpad” 拼成 “thinkppd”或 “thinkd”,使用FuzzyQuery 仍可搜索到正确的结果。

示例:

// FuzzyQuery 模糊查询
FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("name", "thind"));FuzzyQuery fuzzyQuery2 = new FuzzyQuery(new Term("name", "thinkd"), 2);FuzzyQuery fuzzyQuery3 = new FuzzyQuery(new Term("name", "thinkpaddd"));FuzzyQuery fuzzyQuery4 = new FuzzyQuery(new Term("name", "thinkdaddd"));

数值查询

前提:查询的数值字段必须索引。

通过 IntPoint, LongPoint, FloatPoint, or DoublePoint 中的方法构建对应的查询。
以IntPoint为例:

示例:

// 精确值查询
Query exactQuery = IntPoint.newExactQuery("price", 1999900);// 数值范围查询
Query pointRangeQuery = IntPoint.newRangeQuery("price", 499900,1000000);// 集合查询
Query setQuery = IntPoint.newSetQuery("price", 1999900, 1000000, 2000000);

QuerParser查询解析器

用户的查询需求是多变的,我们无法事先知道,也就无法事先编写好构建查询的代码。不同的查询需求只是不同字段的不同基本查询的组合。

比如需求如下:

(name:“联想笔记本电脑” OR simpleIntro :“联想笔记本电脑”) AND type:电脑 AND price:[800000 TO 1000000]

用户的查询需求被很好的描述出来了,我们的搜索程序中得能解读这个描述,并把它转为对应的查询组合。这就是 QueryParser包的功能。

核心API:

Lucene QueryPaser包中提供了两类查询解析器:

  • 传统的解析器:QueryParser、MultiFieldQueryParser
  • 基于新的 flexible 框架的解析器:StandardQueryParser

QueryParser 传统解析器

单默认字段

// 使用的分词器
Analyzer analyzer = new IKAnalyzer4Lucene7(true);
// 要搜索的默认字段
String defaultFiledName = "name";
// 查询生成器(解析输入生成Query查询对象)
QueryParser parser = new QueryParser(defaultFiledName, analyzer);
// 通过parse解析输入,生成query对象
Query query1 = parser.parse("(name:\"联想笔记本电脑\" OR simpleIntro:英特尔) AND type:电脑 AND price:999900");

MultiFieldQueryParser 传统解析器

多默认字段

// 传统查询解析器-多默认字段
String[] multiDefaultFields = { "name", "type", "simpleIntro" };
MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(multiDefaultFields, analyzer);
// 设置默认的组合操作,默认是 OR
multiFieldQueryParser.setDefaultOperator(Operator.OR);
Query query4 = multiFieldQueryParser.parse("笔记本电脑 AND price:1999900");

StandardQueryParser 新标准解析器

StandardQueryParser queryParserHelper = new StandardQueryParser(analyzer);
// 设置默认字段
// queryParserHelper.setMultiFields(CharSequence[] fields);
// queryParserHelper.setPhraseSlop(8);
// Query query = queryParserHelper.parse("a AND b", "defaultField");
Query query5 = queryParserHelper.parse("(\"联想笔记本电脑\" OR simpleIntro:英特尔) AND type:电脑 AND price:1999900","name");

查询解析语法

  • Term词项

    单个词项的表示:电脑
    短语的表示:“联想笔记本电脑”

  • Field字段

    示例1: name:“联想笔记本电脑” AND type:电脑
    如果name是默认字段,则可写成: “联想笔记本电脑” AND type:电脑
    示例2:type:电脑 计算机 手机
    只有第一个是type的值,后两个则是使用默认字段。

  • Term Modifiers 词项修饰符

    通配符

    • ? 单个字符
    • 0个或多个字符
    • 示例:te?t test* te*t
    • 注意:通配符不可用在开头。

    模糊查询

    • 示例: roam~
    • 模糊查询最大支持两个不同字符。
    • 示例: roam~1

    正则表达式

    • /xxxx/
    • 示例:/[mb]oat/

    临近查询

    • 短语后加~移动值
    • 示例:“jakarta apache”~10

    范围查询

    • mod_date:[20020101 TO 20030101] 包含边界值
    • title:{Aida TO Carmen} 不包含边界值

    词项加权

    • 使该词项的相关性更高,通过 ^数值来指定加权因子,默认加权因子值是1
    • 示例:如要搜索包含 jakarta apache 的文章,jakarta更相关,则:jakarta^4 apache
    • 短语也可以: “jakarta apache”^4 “Apache Lucene”
  • 布尔操作符

    Lucene支持的布尔操作: AND, “+”, OR, NOT ,"-"
    OR:“jakarta apache” jakarta 等同于 “jakarta apache” OR jakarta
    AND:“jakarta apache” AND “Apache Lucene”
    +:表示必须包含,+jakarta lucene
    NOT:非,“jakarta apache” NOT “Apache Lucene”,NOT不能单独使用,如NOT "Apache Lucene"是不行的
    -:同NOT,“jakarta apache” - “Apache Lucene”

  • 组合

    字句组合:(jakarta OR apache) AND website
    字段组合:title:(+return +“pink panther”)

  • 转义 \

    对语法字符: + - && || ! ( ) { } [ ] ^ “ ~ * ? : \ / 进行转义。
    如要查询包含 (1+1):2,则使用转义(1+1):2

总结

  • 查询字符串应是由人输入的,而不应是你编程产生。如果你为了用查询解析器,而在你的应用中编程产生查询字符串,不可取,更应该直接使用基本查询API;
  • 未分词的字段,应直接使用基本查询API加入到查询中,而不应使用查询解析器;
  • 对于普通文本字段,使用查询解析器,而其他值字段:如 时间、数值,则应使用基本查询API

Lucene搜索引擎-搜索相关推荐

  1. 建立索引lucene_用Lucene建立搜索索引

    建立索引lucene 本文是我们名为" Apache Lucene基础知识 "的学院课程的一部分. 在本课程中,您将了解Lucene. 您将了解为什么这样的库很重要,然后了解Luc ...

  2. lucene索引搜索_Lucene –快速添加索引和搜索功能

    lucene索引搜索 什么是Lucene? Apache LuceneTM是完全用Java编写的高性能,功能齐全的文本搜索引擎库. 它是一项适用于几乎所有需要全文本搜索的应用程序的技术,尤其是跨平台. ...

  3. 用Lucene建立搜索索引

    本文是我们名为" Apache Lucene基础知识 "的学院课程的一部分. 在本课程中,您将了解Lucene. 您将了解为什么这样的库很重要,然后了解Lucene中搜索的工作方式 ...

  4. adalm pluto_将Apache Pluto与Lucene搜索引擎示例教程集成

    adalm pluto Knowledge information retrieval isn't a luxury requirement that your application may or ...

  5. Pangu分词Lucene.Net搜索使用说明

    首先对Lucene做一个简短的介绍: Lucene不是一个完整的全文检索应用,而是一个用java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能. Lucene的作 ...

  6. lucene搜索引擎总结

    <p>Lucene分析器---Analyzer主要包括分词器和过滤器两种组件</p><p>分词器主要作用是对传入的文本进行切分,将文本按规则切分为一个个可以进入索引 ...

  7. 创新引导工具搜索引擎搜索模块

    采用lucene搜索引擎,我采用的是lucene4.6.0版本. 一.安装 修改pom文件: <dependency><groupId>org.apache.lucene< ...

  8. .net lucene 实战搜索(二)----- 基本之索引

    也许很多朋友没有luncene,但没关系,你可以认为他仅仅是"数据库",或者文档库更合适. 这也是我们网站有又一次数据库服务器被不知道谁提掉网线,仍然运行了1天没人发现,-_-!. ...

  9. java搜索项目内的异常_java中用Lucene做搜索,在建索引时遇到的2个异常

    版本信息: jdk: 1.6 lucene: 3.2.0 情况是这样的,现在项目用lucene做搜索,我在服务器上跑了个后台线程用于建索引(每次最多从数据库中取出2w条),隔10分钟会跑一次,但是 隔 ...

最新文章

  1. 《权力的游戏》最终季上线!谁是你最喜爱的演员?这里有一份Python教程 | 附源码...
  2. 多协程爬取中大微博内容(以及转发数,点赞数,评论数)
  3. Spring Boot ES 实战,值得参考!
  4. 网友提问:关于CX_VSI_SYSTEM_ERROR异常,Fiori病毒扫描参数文件
  5. android蓝牙通信_Flutter通过BasicMessageChannel实现Flutter 与Android iOS 的双向通信
  6. CSS3 Flex布局(伸缩布局盒模型)学习
  7. 车联网领域,传统TSP企业做错了什么 ?
  8. 7.JasperReports学习笔记7-applet打印
  9. Spring MVC实现Junit Case
  10. 人工智能(12)----宽动态摄像机技术
  11. python threading.lock
  12. DNS 基础知识及 Linux DNS 服务器操作知识
  13. 第2章—装配Bean—自动化装配Bean
  14. php显示地址栏携带的错误信息_php-fpm搭建及加固
  15. 2020-1024=996(程序员节)
  16. codeforces 863B Kayaking
  17. zoj 3551 Bloodsucker 概率DP
  18. 2:STM32CubeMX配置STM32F103C8T6驱动-SPI驱动
  19. 二字动词 复盘赋能_落地、赋能、共创、共建、复盘,互联网圈的漂亮词儿,你懂几个?...
  20. android+制作一个锁屏,手机个性锁屏怎么做?教你如何制作DIY手机锁屏图文教程...

热门文章

  1. C++:学生管理系统
  2. mysql oracle创建视图索引吗_Oracle视图,索引,序列
  3. java四叶玫瑰_java编一个四叶玫瑰曲线 不显示曲线
  4. 【Solr】--简介
  5. 【网络篇】第十七篇——IP协议详解
  6. 判断平面多边形的凹凸性
  7. 开源四轴无人机系统迈入新的阶段!
  8. 计算机文件丢失系统无法启动,文件损坏或丢失windows无法启动_windows无法启动文件损坏解决方法...
  9. CentOS7救援模式修复系统丢失文件
  10. 【转】ASP六大对象介绍