目录

  返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html

  本项目Demo已上传GitHub,欢迎大家fork下载学习:https://github.com/kencery/Lucene_Compass(项目内部有很详细的注释)

1. 搜索思路

  a. 当用户在搜索的时候,先在词汇表中查找,得到符合条件的文档编号列表,再根据文档编号去索引库中得到数据(Document)。

  b. Lucene实现搜索的思路

    b.1 首先把需要查询的字符串转换为Query对象,把查询字符串转换为Query需要使用QueryParser、MultiFieldQueryParser,查询字符串首先也要经过分词器(Analyzer),要求搜索时使用的Analyzer和建立索引的时候使用的Analyzer要一致,否则极有可能搜索不出正确的结果。

    b.2 调用indexSearcher.search()进行查询得到结果,此方法返回值为TopDocs,是包含结果的多个信息的一个对象,其中有totalHits代表总记录数,ScoreDoc数组代表一个结果的相关度得分和文档编号等信息的对象。

    b.3 取出需要的数据文档编号列表,调用Document doc=indexSearcher.doc(docId)以取出指定编号对应的Document数据。

2. 理解核心搜索类

  a.  public class org.apache.lucene.search.IndexSearcher

    a.1 IndexSearch是用来在建立好的索引上进行搜索的,它提供了很多搜索方法,其中一些在抽象基类Searcher中实现

    a.2 它只能以只读的方式打开一个索引,所以可以有多个IndexSearcher的实例在一个索引上进行操作。

    a.3 在使用完IndexSearcher后,需要释放资源,调用方法:indexSearcher.getIndexReader().close();

  b. public final class org.apache.lucene.index.Term

    b.1 Term是搜索的基本单元,一个Term对象由两个Sting类型的域组成,字段的名称和字段的值

    b.2  在搜索时,你可以创建Term对象并和TermQuery同时使用,其中第一个参数代表了要在文档的哪一个Field上进行查找,第二个参数代表了要查询的关键字

      Query query=new TermQuery(new Term("content","lucene"));

      TopDocs topDocs= indexSearcher.search(query,100 );  //返回查询出来的前n条结果

    b.3 这段代码使用Lucene查找出content字段中含有单词lucene的所有文档,因为TermQuery对象继承自它的抽象父类Query,所以你可以在等式的左边用Query类型。

  c.  public abstract class org.apache.lucene.search.Query

    c.1 Query是一个抽象类,这个类的目的是把用户输入的查询字符串封装成Lucene能够识别的Query。

    c.2 Query包含了很多子(必须通过一系列子类来表达检索的具体需求,在4个模块中有说明),具体请同时按住Ctrl+T查看

  d. public class org.apache.lucene.search.TermQuery

    d.1 TermQuery是抽象类Query的一个子类,他同时也是Lucene支持的最为基本的一个查询类。

    d.2 生成一个TermQuery对象由如下语句完成(它的构造函数主要只接受一个参数,那就是一个Term对象)。

      TermQuery query=new TermQuery(new Term("content","lucene"));

  e. public class org.apache.lucene.search.TopDocs

    e.1 TopDocs是用来保存搜索的结果的,思路是:指向相互匹配的搜索条件的前N个搜索结果,它是指针的简单容器指向他们的搜索结果输出的文档。

    e.2 基于性能的考虑,TopDocs的实例并不是从索引中加载所有匹配查询的所有文档,而是每次按照你给的条件查询出一小部分展现给用户(分页原理)。

  f.QueryParser和MultiFieldQueryParser

    f.1 QueryParser查询分析器,处理用户输入的查询条件,把用户输入的非格式话检索词转化成后台可以使用的Query对象。

    f.2 MultiFieldQueryParser是QueryParser的子类,与父类相比,MultiFieldQueryParser可以在多个属性中搜索。

3. 关键字搜索的大致实现

  a. 代码以在github上开源,地址:https://github.com/kencery/Lucene_Compass

     /**
* 测试搜索
* @throws Exception
*/
@Test
public void testSearch() throws Exception {
//1 搜索条件
String queryCondition="lucene";
//2 执行搜索(lucene)
List<Article> articles=new ArrayList<Article>();
//--------------------------搜索代码-----------------------------
Directory directory=FSDirectory.open(Paths.get("./indexDir/")); //索引库目录
Analyzer analyzer=new StandardAnalyzer(); //分词器 //2.1 把查询字符串转为Query对象(只在title中查询)
QueryParser queryParser=new QueryParser("title",analyzer);
Query query=queryParser.parse(queryCondition); //2.2 执行搜索得到结果
IndexReader indexReader=DirectoryReader.open(directory);
IndexSearcher indexSearcher=new IndexSearcher(indexReader);
TopDocs topDocs= indexSearcher.search(query, 100); //返回查询出来的前n条结果 Integer count= topDocs.totalHits; //总结果数量
ScoreDoc[] scoreDocs=topDocs.scoreDocs; //返回前N条结果信息 //2.3 处理结果
for (int i = 0; i < scoreDocs.length; i++) {
ScoreDoc scoreDoc=scoreDocs[i];
int docId=scoreDoc.doc;
System.out.println("得分是:"+scoreDoc.score+",内部编号是:"+docId);
//根据内部编号取出真正的Document数据
Document doc=indexSearcher.doc(docId);
//将document转化为Article
Article article=new Article(Integer.parseInt(doc.get("id")), doc.get("title"), doc.get("content"));
articles.add(article);
}
//------------------------------------------------------------
//3 控制台显示结果
System.err.println("总结果数:"+count);
for (Article article : articles) {
System.out.println("查询结果为:"+article);
}
indexSearcher.getIndexReader().close();
}

4.内建Query对象阐述

  a. BooleanQuery 布尔搜索,对应的查询语句:

    a.1 BooleanQuery是实际开发过程中经常使用的一种查询,它其实就是一个组合的Query,在使用中的时候可以把各种Query对象添加进去并且标明它们之间的逻辑关系。

    a.2 BooleanQuery是可以嵌套的(BooleanQuery是一个布尔子句的容器)

      (1) 一个BooleanQuery可以成为另一个BooleanQuery的条件子句。

      (2) 布尔型的子句数目不能跟你超过1024。

    a.3 public void add(Query query,BooleanClause.Occur occur),BooleanClause表示布尔查询子句关系的类,包括:BooleanClause.Occur.MUST、BooleanClause.Occur.MUST_NOT、BooleanClause.Occur.SHOULD,它含有以下6种组合。

      (1) MUST和MUST:取得两个查询子句的交集。

      (2) MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应的查询子句的检索结果

      (3) MUST_NOT和MUST_NOT:无意义,检索无结果

      (4) SHOULD和MUST:无意义,结果为MUST子句的检索结果

      (5) SHOULD和MUST_NOT:SHOULD功能同MUST,相当于MUST和MUST_NOT的检索结果

      (6) SHOULD和SHOULD:表示"或"的关系,最终检索结果为所有检索子句的并集。

        Query query1=new MatchAllDocsQuery();

        Query query2=NumericRangeQuery.newIntRange("id", 5, 15, true, false);

        booleanQuery.add(query1,Occur.MUST);

        booleanQuery.add(query2,Occur.MUST_NOT);

          对应的查询字符串为:+*:* -id:[5 TO 15}

  b. NumericRangeQuery 范围搜索

    b.1 NumericRangeQuery.newIntRange(String field,Integer min,Integer max,boolean minInclusive,boolean maxInclusive);  布尔型的后面的两个参数表示是否可以将两个临界值也加入到搜索中。

      例如:Query query=NumericRangeQuery.newIntRange("id", 5, 15, true, false);

        对应的查询语句:对应的查询字符串为:id:[5 TO 15}

  c. PrefixQuery 前缀查询,查询出某个字段以什么开头的信息

    Term term=    new Term("content","这是");

    PrefixQuery query=new PrefixQuery(term);

      对应的查询语句:content:这是*

  d. PhraseQuery短语查询

    d.1 PhraseQuery提供了一种为"坡度"的参数,用于表示词组的两个字之间可以插入无关单词的个数

      PhraseQuery phraseQuery=new PhraseQuery();

      phraseQuery.add(new Term("title","lucene"));

      phraseQuery.add(new Term("title","框架"));

      phraseQuery.setSlop(5);  //之间的间隔最大不能超过5个

        对应的查询语句:title:"lucene 框架"~5

  e. FuzzyQuery模糊查询(FuzzyQuery(Term term,int maxEdits))

    e.1 maxEdits最小相似度,默认为2,数字越小,查询结果越少,取值范围为0、1、2,当为0的时候相当于TermQuery。

      Query query=new FuzzyQuery(new Term("title","lucenX"),2);

        对应的查询语句:title:lucenX~2

  f. WildcardQuery通配符搜索

    f.1 *代表0到多个字符,?代表一个单一的字符。

      Query query=new WildcardQuery(new Term("title","lu*n?"));

        对应的查询语句是:title:lu*n?

  g. MatchAllDocsQuery搜索全部

    Query query=new MatchAllDocsQuery();

      对应的查询语句是:*:*

5. 排序、过滤、高亮

  a. 这部分内容在demo中备注已经非常详细,如果大家想去了解,请去github上下载项目自行查看(里面有详细备注)。

  b. GitHub地址是:https://github.com/kencery/Lucene_Compass/tree/master/Lucene_5.5

  c. 排序对应分支是:lucene_seven,过滤对应的分支是:lucene_eight,高亮对应的分支是:lucene_six

    希望大家能从中间学到东西,如有疑问,请留言或者去GitHub上看LuceneDemo或者添加我的QQ,我们共同探讨。

Apache Lucene(全文检索引擎)—搜索的更多相关文章

  1. 【Lucene】Apache Lucene全文检索引擎架构之搜索功能3

    上一节主要总结了一下Lucene是如何构建索引的,这一节简单总结一下Lucene中的搜索功能.主要分为几个部分,对特定项的搜索:查询表达式QueryParser的使用:指定数字范围内搜索:指定字符串开 ...

  2. Apache Lucene(全文检索引擎)—创建索引

    目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...

  3. Apache Lucene(全文检索引擎)—分词器

    目录 返回目录:http://www.cnblogs.com/hanyinglong/p/5464604.html 本项目Demo已上传GitHub,欢迎大家fork下载学习:https://gith ...

  4. 【Lucene】Apache Lucene全文检索引擎架构之入门实战1

    Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的 ...

  5. 【Lucene】Apache Lucene全文检索引擎架构之中文分词和高亮显示4

    前面总结的都是使用Lucene的标准分词器,这是针对英文的,但是中文的话就不顶用了,因为中文的语汇与英文是不同的,所以一般我们开发的时候,有中文的话肯定要使用中文分词了,这一篇博文主要介绍一下如何使用 ...

  6. 【Lucene】Apache Lucene全文检索引擎架构之构建索引2

    上一篇博文中已经对全文检索有了一定的了解,这篇文章主要来总结一下全文检索的第一步:构建索引.其实上一篇博文中的示例程序已经对构建索引写了一段程序了,而且那个程序还是挺完善的.不过从知识点的完整性来考虑 ...

  7. Lucene 全文检索引擎

    Apache Lucene PS: 苦学一周全文检索,由原来的搜索小白,到初次涉猎,感觉每门技术都博大精深,其中精髓亦是不可一日而语.那小博猪就简单介绍一下这一周的学习历程, 仅供各位程序猿们参考,这 ...

  8. Lucene全文检索引擎

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  9. Lucene:基于Java的全文检索引擎简介

    Lucene:基于Java的全文检索引擎简介 Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引/检索引擎--Lucene Lucene不是一个完整的全文索引应用,而是是一个用J ...

随机推荐

  1. Oozie分布式任务的工作流——脚本篇

    继前一篇大体上翻译了Email的Action配置,本篇继续看一下Shell的相关配置. Shell Action Shell Action可以执行Shell脚本命令,工作流会等到shell完全执行完毕 ...

  2. css+div常用属性备忘录

    学习软件设计有一年多了,明年五月就要毕业了.回头看看发现自己其实挺差劲的. 最近开通了博客所以就整理了一下笔记,在这里发布一下自己以前学习css时总是记不住去翻书又很常用的属性,都是一些很基础的. 大 ...

  3. Solr的原理及在项目中的使用实例.

    前面已经讲过 如果安装及配置Solr服务器了, 那么现在我们就来正式在代码中使用Solr.1,这里Solr主要是怎么使用的呢?  当我们在前台页面搜索商品名称关键词时, 我们这时是在Solr库中去查找 ...

  4. Java 对象引用方式 —— 强引用、软引用、弱引用和虚引用

    Java中负责内存回收的是JVM.通过JVM回收内存,我们不需要像使用C语音开发那样操心内存的使用,但是正因为不用操心内存的时候,也会导致在内存回收方面存在不够灵活的问题.为了解决内存操作不灵活的问题 ...

  5. 让easyui datagrid支持bootstrap的tooltip

    让easyui datagrid支持bootstrap的tooltip 发表于 下午 1:53 by ylpro.net & 分类 Java. Easyui在1.3.3版本之前是不支持tool ...

  6. UpdateData(TRUE)与UpdateData(FALSE)的使用

    二者是更新对话框的控件与变量. 1.先要建立对应关系 如 编辑框IDC_Edit  和 变量 m_name DDX_Text(pDX, IDC_EDIT, m_name); 2.若是在编辑框输入名字 ...

  7. 【转】C#语言之“string格式的日期时间字符串转为DateTime类型”的方法

    方法一:Convert.ToDateTime(string) string格式有要求,必须是yyyy-MM-dd hh:mm:ss ================================== ...

  8. Python标准模块--logging

    1 logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等:相比print,具备如下优点: 可以通过设置不同 ...

  9. 国内版Office 365和Azure AAD绑定的问题及解决方案

      背景: 1. 开发人员要做的事情,是希望在应用程序里面能调用Office 365 的API(Microsoft Graph)来动态添加Office 365账号 2. 如果需要调用这些API,必须在 ...

  10. IDDD 实现领域驱动设计-由贫血导致的失忆症

    啰嗦几句 年前的时候,在和 netfocus 兄,以及对 DDD 感兴趣园友的探讨过程中,我发现自己有很多不足的地方,对 DDD 的了解也只是皮毛而已,代码写的少,DDD 的基本概念也不是很清楚,空有 ...