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

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

1. 对特定项的搜索

  要使用Lucene的搜索功能,首先得有索引,也就是说Lucene首先得针对特定的文件生成特定的索引,然后我们才能搜索,这在第一节里描述的很清楚,那么构建索引的例子也是使用第一节中的例子,在这就不再赘述了,然后生成了索引后,如何来搜索呢?先看第一种搜索方式:对特定项的搜索。使用的文件和建立的索引还是使用第一节的那些,生成好了索引后,就可以对特定项进行搜索了。

public class SearchTest {

    private Directory dir;
    private IndexReader reader;
    private IndexSearcher search; 

    @Before
    public void setUp() throws Exception {

        dir = FSDirectory.open(Paths.get("D:\\lucene")); //索引的目录在D:\\lucene
        reader = DirectoryReader.open(dir); //根据目录获取IndexReader
        search = new IndexSearcher(reader); //根据IndexReader获取IndexSearcher
    }

    @After
    public void tearDown() throws Exception {
        reader.close(); //关闭InderxReader
    }

    //对特定项进行搜索
    @Test
    public void testTermQuery() throws Exception {
        String searchField = "contents";
        String q = "particular";
        Term term = new Term(searchField, q);
        Query query = new TermQuery(term);
        TopDocs hits = search.search(query, 10);
        System.out.println("匹配" + q + "总共查询到" + hits.totalHits + "个文档");
        for(ScoreDoc score : hits.scoreDocs) {
            Document doc = search.doc(score.doc);
            System.out.println(doc.get("fullPath"));
        }
    }
}

  首先初始化IndexSearcher,在搜索的时候,要在特定的Field中对特定的字符串q进行搜索,由上面的程序可知,我要在contents字段中搜索particular这个字符串。contents是在建立索引的时候建立的,包括程序最后一行中的fullPath字段,都是在建立索引的时候创建的。有了Field和搜索字符串后,就可以生成一个搜索项Term了,然后根据这个搜索项创建一个搜索。最后就可以搜索出包含这个字符串的文件的路径。

  这是针对特定项进行搜索,为什么叫针对特定项呢?因为如果我搜索particul,那么结果就为0,也就是说我必须是针对具体的一个单词,也就是说Lucene在建立索引的时候也是根据一个个单词来的,如果我只搜索单词的一部分,那么是搜不到的,所以这种针对特定项搜索其实用的不多,因为在实际中,我如果搜索particul的话,理论上应该能将particular搜出来才对。所以要用到查询表达式QueryParser。

2. 使用查询表达式QueryParser搜索

首先来看一下如何使用这个QueryParser。

@Test
public void testQueryParser() throws Exception {
    Analyzer analyzer = new StandardAnalyzer(); //标准分词器,会自动去掉空格啊,is a the等单词
    String searchField = "contents";
    String q = "particular";    //OR AND particular~
    QueryParser parser = new QueryParser(searchField, analyzer); //查询解析器
    Query query = parser.parse(q); //通过解析要查询的String,获取查询对象
    TopDocs docs = search.search(query, 10);//开始查询,查询前10条数据,将记录保存在docs中
    System.out.println("匹配" + q + "总共查询到" + docs.totalHits + "个文档");
    for(ScoreDoc scoreDoc : docs.scoreDocs) { //取出每条查询结果
        Document doc = search.doc(scoreDoc.doc); //scoreDoc.doc相当于docID,根据这个docID来获取文档
        System.out.println(doc.get("fullPath")); //fullPath是刚刚建立索引的时候我们定义的一个字段
    }
}

  从程序中可以看出,初始化QueryParser需要传入一个分词器,这里使用的是标准分词器,然后跟上面一样,得指定具体的Field和要查询的字符串。这看起来好像和上面根据特定项来搜索没什么两样,其实不然,使用QueryParser的好处就在于初始化查询字符串q的时候,是有语法的,程序中只是简单的查询一个particular单词而已。

  如果我将q改成”particular OR Unicode”,那么Lucene就会查询出所有包含particular或Unicode(不区分大小写)的文档,这里的OR也可以省略不写。同样的,如果我把OR改成AND,那么就是查询出所有包含particular且包含Unicode的文档。那么如果我要类似于上面提到的模糊查询呢?比如我输入particul想查出particular咋整呢?可以将q定义为“particul~”,这样就OK了。实际中用的比较多的是这个QueryParser,这一块更多的内容可以看一下官方文档。

3. 指定数字范围搜索

  这个主要用于某个字段是int型的,然后可以根据这个字段来搜索,可以搜索某两个int值范围内的所有项。为了模拟这个场景,我使用上一节的例子来建立索引,因为里面有id,将其修改为Integer类型即可。然后看下如何指定数字范围内搜索。

@Test
public void testNumericRangeQuery() throws Exception {
    NumericRangeQuery<Integer> query = NumericRangeQuery.newIntRange("id", 1, 2, true, true);
    TopDocs hits = search.search(query, 10);
    System.out.println("总共查询到" + hits.totalHits + "个文档");
    for (ScoreDoc score : hits.scoreDocs) {
        Document doc = search.doc(score.doc);
        System.out.println(doc.get("id"));
        System.out.println(doc.get("city"));
        System.out.println(doc.get("desc"));
    }
}

  首先得要创建一个NumericRangeQuery对象,初始化的时候第一个参数是字段名,第二个和第三个参数是始末数,后面两个是包含大小写,一般都设置为true,后面就跟之前的查询一样了。上面的程序可以查询到两个记录。

4. 指定字符串开头搜索

  这个和上面的数字范围内搜索有点类似,只不过搜索的条件不同,初始化也不同,指定字符串开头搜索的话需要先创建一个PrefixQuery对象,将要搜索的字段和开头的字符串传进去,然后再搜索。如下搜索city中以s开头的所有项。

@Test
public void testPrefixQuery() throws Exception {
    PrefixQuery query = new PrefixQuery(new Term("city", "s"));
    TopDocs hits = search.search(query, 10);
    System.out.println("总共查询到" + hits.totalHits + "个文档");
    for (ScoreDoc score : hits.scoreDocs) {
        Document doc = search.doc(score.doc);
        System.out.println(doc.get("id"));
        System.out.println(doc.get("city"));
        System.out.println(doc.get("desc"));
    }
}

5. 多条件查询(组合查询)

  多条件查询又称为组合查询,顾名思义,就是将多个查询条件组合到一起进行查询,这个就比较厉害了。比如我现在想组合上面两个查询,首先id为1到2之间,然后city又是s开头的,可以这么做:

@Test
public void testBooleanQuery() throws Exception {
    NumericRangeQuery<Integer> query1 = NumericRangeQuery.newIntRange("id", 1, 2, true, true);
    PrefixQuery query2 = new PrefixQuery(new Term("city", "s"));
    BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();

    booleanQuery.add(query1, BooleanClause.Occur.MUST);
    booleanQuery.add(query2, BooleanClause.Occur.MUST);

    TopDocs hits = search.search(booleanQuery.build(), 10);
    System.out.println("总共查询到" + hits.totalHits + "个文档");
    for (ScoreDoc score : hits.scoreDocs) {
        Document doc = search.doc(score.doc);
        System.out.println(doc.get("id"));
        System.out.println(doc.get("city"));
        System.out.println(doc.get("desc"));
    }
}

  组合查询使用的是BooleanQuery,然后组合的条件还是上面的那些条件,这些条件中原来该使用什么类初始化还是使用那些类初始化,只是往BooleanQuery中加就行了。这很方便,一般查询条件多的时候,就可以采用这种组合的查询方式来查询。



—–乐于分享,共同进步!

—–我的博客主页:http://blog.csdn.net/eson_15

时间: 2024-10-10 13:34:29

【Lucene】Apache Lucene全文检索引擎架构之搜索功能的相关文章

Lucene作为一个全文检索引擎

Lucene作为一个全文检索引擎,其具有如下突出的优点: (1)索引文件格式独立于应用平台.Lucene定义了一套以8位字节为基础的索引文件格式,使得兼容系统或者不同平台的应用能够共享建立的索引文件. (2)在传统全文检索引擎的倒排索引的基础上,实现了分块索引,能够针对新的文件建立小文件索引,提升索引速度.然后通过与原有索引的合并,达到优化的目的. (3)优秀的面向对象的系统架构,使得对于Lucene扩展的学习难度降低,方便扩充新功能. (4)设计了独立于语言和文件格式的文本分析接口,索引器通过

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

Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的免费开源工具.就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库.--<百度百科> 这篇博文主要从两个方面出发,首先介绍一下Lucene中的全文搜索原理,其次通过程序示例来展现如何使用Lucene.关于全文搜索原理部分我上网搜索了一下,也看了好几篇文章,最后在写这篇文

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

Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的免费开源工具.就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库.——<百度百科> 这篇博文主要从两个方面出发,首先介绍一下Lucene中的全文搜索原理,其次通过程序示例来展现如何使用Lucene.关于全文搜索原理部分我上网搜索了一下,也看了好几篇文章,最后在写这篇文

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

前面总结的都是使用Lucene的标准分词器,这是针对英文的,但是中文的话就不顶用了,因为中文的语汇与英文是不同的,所以一般我们开发的时候,有中文的话肯定要使用中文分词了,这一篇博文主要介绍一下如何使用smartcn中文分词器以及对结果的高亮显示. 1. 中文分词 使用中文分词的话,首先到添加中文分词的jar包. <!-- lucene中文分词器 --> <dependency> <groupId>org.apache.lucene</groupId> <

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

上一篇博文中已经对全文检索有了一定的了解,这篇文章主要来总结一下全文检索的第一步:构建索引.其实上一篇博文中的示例程序已经对构建索引写了一段程序了,而且那个程序还是挺完善的.不过从知识点的完整性来考虑,我想从Lucene的添加文档.删除文档.修改文档以及文档域加权四个部分来展开对构建索引的总结,也便于我后期的查看.会重点分析一下删除文档(因为有两中方式)和文档域加权这(实际中会用到比较多)两个部分. 1. 准备阶段 新建一个maven工程,pom.xml如下: <project xmlns=&quo

Lucene:基于Java的全文检索引擎简介 (zhuan)

http://www.chedong.com/tech/lucene.html ********************************************** Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引引擎Lucene简介:关于作者和Lucene的历史 全文检索的实现:Luene全文索引和数据库索引的比较 中文切分词机制简介:基于词库和自动切分词算法的比较 具体的安装和使用简介:系统结构介绍和演示 Hacking Lucene:简化的查询分析器,删除的

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

Lucene是一个基于Java的全文索引工具包. 基于Java的全文索引引擎Lucene简介:关于作者和Lucene的历史 全文检索的实现:Luene全文索引和数据库索引的比较 中文切分词机制简介:基于词库和自动切分词算法的比较 具体的安装和使用简介:系统结构介绍和演示 Hacking Lucene:简化的查询分析器,删除的实现,定制的排序,应用接口的扩展 从Lucene我们还可以学到什么 另外,如果是在选择全文引擎,现在也许是试试 Sphinx的时候了:相比Lucene速度更快, 有中文分词的

全文检索:Apache Lucene框架入门实例

一 简介 Lucene属于Apache开源项目的一部分,是一个开源的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言) Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎.在Java开发环境里Lucene是一个成熟的免费开源工具.就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序

【手把手教你全文检索】Apache Lucene初探

PS: 苦学一周全文检索,由原来的搜索小白,到初次涉猎,感觉每门技术都博大精深,其中精髓亦是不可一日而语.那小博猪就简单介绍一下这一周的学习历程,仅供各位程序猿们参考,这其中不涉及任何私密话题,因此也不用打马赛克了,都是网络分享的开源资料,当然也不涉及任何利益关系. 如若转载,还请注明出处——xingoo 讲解之前,先来分享一些资料 首先呢,学习任何一门新的亦或是旧的开源技术,百度其中一二是最简单的办法,先了解其中的大概,思想等等.这里就贡献一个讲解很到位的ppt.已经被我转成了PDF,便于搜藏