• Lucene第五篇:Lucene搜索索引时常用的核心类 原创

  • user image
    • jack
    • 2018-04-04 19:39:17 +0800

接第四篇blog,这里我们介绍下Lucene搜索索引时常用核心类。

1、Term

        Term对象是搜索功能的基本单元。你可以直接创建一个term对象。Term titleTerm = new Term("title", queryText);

         但是注意,Term对应最小的索引片段,对应索引文件的分词结果,即精确匹配索引词条,并不是对应内容词条。举个例子:在第三篇中我们使用的是StandardAnalyzer来分词的,blog会被分解为一个个单独的字。所以在使用term搜索时,你会发现你可以所搜索到单独的汉字“问”和“题”,但是不能搜索到词组“问题”。

下面的代码依赖于第三篇程序所创建的索引。

public class Test {

    public static void main(String[] args) throws IOException, ParseException {

        search("问题");//搜索到 0 篇blog

        search("问");//搜索到 1 篇blog

        search("题");//搜索到 1 篇blog

    }

    public static void search(String queryText) throws IOException, ParseException {

        // 指定索引文件目录

        String indexDir = "d:/lucence/index";

        File ifDir = new File(indexDir);

        Path path = ifDir.toPath();

        FSDirectory fSDirectory = FSDirectory.open(path);

        IndexReader indexReader = DirectoryReader.open(fSDirectory);

        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        // 搜索标题

        Term titleTerm = new Term("title", queryText);

        Query titleQuery = new TermQuery(titleTerm);

        // 搜索前100匹配度最高的document

        TopDocs topdocs = indexSearcher.search(titleQuery, 100);

        ScoreDoc[] scoreDocs = topdocs.scoreDocs;

        System.out.println("搜索到 " + scoreDocs.length + " 篇blog:");

        for (ScoreDoc scoreDoc : scoreDocs) {

            Document document = indexSearcher.doc(scoreDoc.doc);

            System.out.println(document.get("uuid"));

            System.out.println(document.get("title"));

            System.out.println(scoreDoc.score);

            System.out.println("--");

        }

        System.out.println();

    }

}

 

2、Query

       常用的Query子类如下。

  • TermQuery

             TermQuery是lucene查询中最基本的一种原子查询,从它的名字Term我们可以看出,它只能针对一个字段进行精确查找查询。但是应该注意的是,这里的“精确查找”是对应在索引文件是得到的分词结果,即精确匹配索引词条。结合Term对象的例子应该很容易理解。

  • BooleanQuery:  “与或”搜索,它能进行组合查询。
  • WildcardQuery:通配符搜索
  • PhraseQuery:短语搜索
  • MultiPhraseQuery:多短语搜索
  • PrefixQuery:前缀搜索
  • FuzzyQuery:模糊搜索
  • RegexpQuery:正则表达式搜索
  • TermRangeQuery:在某一范围内搜索
  • NumericRangeQuery:
  • ConstantScoreQuery:
  • DisjunctionMaxQuery:
  • MatchAllDocsQuery:

 

3、QueryParser

       QueryParser主要用于单个域的搜索,而MultiFieldQueryParser则用于多个域(Field)的搜索,其构造方法和具体使用和QueryParser类似。这与上面的TermQuery用于域(Field)的索引词条搜索不同。对于上面Lucene内置查询对象,在实际的项目开发中应用的不多。一般用QueryParser去获取查询对象,其内部基本实现了所有的内置查询对象。

 

4、IndexReader

        IndexReader是一个抽象类,为访问某个时间点索引提供了接口。通过IndexWriter对索引所做的任何更改都将不可见,除非你打开新的IndexReader。磁盘索引的IndexReader实例通常是通过调用一个静态DirectoryReader.open(org.apache.lucene.store.Directory)方法来得到的。

        为了减少开销和提高效率,建议以下几点:

        如果您的IndexWriter处于进程中,最好使用DirectoryReader.open(IndexWriter)来获取IndexReader。这中获取IndexReader的方式,就是Lucene中的近实时搜索。

        当您需要重新打开以查看对索引的更改时,最好使用DirectoryReader.openIfChanged(DirectoryReader),因为新阅读器将尽可能地与前一个共享资源。

        注意:IndexReader实例是完全线程安全的,这意味着多个线程可以同时调用其任何方法。如果您的应用程序需要外部同步,则不应该在IndexReader实例上同步;改用你自己的(非Lucene)对象。

 

5、IndexSearcher

用于执行搜索,通常只用调用其search方法,例如:IndexSearcher.search(Query,int) 。出于性能原因,如果您的索引不发生更改,在每次的查询中您应该共享一个IndexSearcher实例,而不是每次搜索都去重新创建一个IndexSearcher实例。如果你的索引发生更改,并且你希望在搜索结果中体现变化,则应使用DirectoryReader.openIfChanged(DirectoryReader)获取新的IndexReader实例,然后从中创建一个新的IndexSearcher。如下面的代码:

public IndexSearcher getIndexSearcher() throws IOException{

        if(indexReader==null){

            indexReader = DirectoryReader.open(fSDirectory);

        }else {

            //openIfChanged这个方法类似3.x中的reader.reopen方法,这样就实现了近实时搜索,避免多次新建IndexReader耗费系统资源

            IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader) indexReader);

            if(newReader!=null){

                // 要记得将原来的 IndexReader 对象关掉

                indexReader.close();

                indexReader = newReader;

            }

        }

        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        return indexSearcher;

    }

       另外,如果使用近实时搜索,使用(DirectoryReader.open(IndexWriter))创建IndexReader,从它创建一个新的IndexSearcher相对高效和减少消耗。

 

6、TopDocs

       TopDocs类是一个简单的指针容器,指针一般指向前N个匹配度最高的搜索结果Document。其方法和属相相对较少,这里简单说明下。

    1)TopDocs.totalHits 匹配搜索条件的文档数量,它是实际数量与IndexSearcher.search(query, N)方法中的N无关;

  2)TopDocs.scoreDocs 所搜结果集的ScoreDoc对象数组;

  3)TopDocs.getMaxScore()  返回搜索遇到的最大比分的值。

  • 查看 0 条评论
登 录 | 注册账号,开始评论。