1.  学習プログラム

1、ケーススタディ:フルテキスト検索を実現するためにどのように、フルテキスト検索とは何ですか

2、Luceneのフルテキスト検索処理

a)のインデックスを作成

b)は、クエリインデックス

3、開発環境を設定します

4、インデックス・ライブラリを作成します

5、クエリインデックスデータベース

図6に示すように、分析装置の分析

効果セグメンテーションA)試験アナライザ

b)は、サードパーティ製の中国アナライザ

図7に示すように、インデックスデータベースを維持します

a)のドキュメントを追加

b)の文書を削除します

c)のドキュメントを変更

8、Luceneの高度なクエリLuceneクエリ

a)はクエリのサブクラスを使用して問い合わせます

  1. MatchAllDocsQuery
  2. TermQuery
  3. NumericRangeQuery
  4. BooleanQuery

b)の使用QueryParser

  1. QueryParser
  2. MulitFieldQueryParser

2.  ケース

キーワードを見つける必要があるなど、キーワードによるファイルの検索、ファイルの任意のファイル名やファイルの内容をファイル検索機能を実装します。また、中国語の単語、および複数の条件のクエリをサポートするために、必要に応じて照会することができます。

以下に示すように、この場合に元のコンテンツは、ディスク上のファイルです。

 

 

3.  要件分析

3.1。  データベース検索

データベースの検索は、多くの場合、クエリを実行するSQL文を使用して、達成することが容易で、すぐに結果を得ることができます。

なぜそれがデータベースを検索するのは簡単ですか!

データベースに格納されたデータが規則的であるので、データフォーマットと行と列があり、データ長が固定されています。

 

3.2。  データ分類

構造化データと非構造化データ:一般的に私たちの生活のデータは、2つのタイプに分けられます。

構造化データ:そのようなデータベース、メタデータなどの固定データ・フォーマットまたは有限の長さを有することを意味します。

非構造化データ:電子メール、ワード文書やその他としてディスク上の長いファイルやデータの無い固定フォーマットを、Zhibuding

 

3.3。  非構造化データのクエリ方法

(1)順次走査方式(シリアルスキャン)

そのような文字列の内容を含むファイルを探して、いわゆる順次走査は、各ドキュメントのために、この文書は、この文字列が含まれている場合、この文書は、我々が探している、仕上げに開始、一つの文書を見ていますファイル、次の上のファイル、あなたがスキャンしたすべての文書を持っているまで。このような検索ウィンドウの使用なども、ファイルの内容を検索ではなく、遅いことができます。

(2)フルテキスト検索(全文検索)

非構造化データから抽出された情報の一部は、それが特定の構造を持たせるために再編成し、比較的高速検索の目的を達成するように、このデータ構造のいくつかは、検索されます。この情報は、その後、非構造化データから抽出された部分を再編成され、我々はそれを呼び出すインデックス

たとえば、次の辞書。ラジカルインデックステーブルとインデックステーブルのふりがな辞書と等価である音節とラジカルインデックステーブルのない辞書が存在しない場合、すべての単語の解釈は、非構造化され、辞書に単語を見つけるだけ広大なを注文することができますスキャンします。しかし、情報語の一部を抽出することができるそのような発音のように、構成され、それぞれ、わずか数はそれぞれ、次に発音が出て特定の順序で配置され、列挙することができ、より多くの、構造化された最初と最後の点ですページ数この言葉の詳細な説明に発音ポイント。言葉の解釈です - 私たちは、あなたが私たちの非構造化データを見つけることができ、自分のページを指摘し、音声発音に構造化された検索を検索します。

このインデックス処理まず、その後、インデックスは、フルテキスト検索(全文検索)を検索するために呼び出されます。

インデックス作成プロセスは非常に時間がかかりますが、一度作成したインデックスは主にフルテキスト検索クエリを扱う、複数回使用することができ、これが時間のかかるインデックスを作成するためには、それだけの価値があります。

3.4。  全文検索を実現する方法

あなたはLuceneのフルテキスト検索を使用することができます。Luceneには、Apache、フルテキスト検索エンジンのツールキットの下でオープンソースです。これは、完全なクエリエンジンとインデックスエンジン、テキスト分析エンジンの一部を提供します。Luceneのは、ソフトウェア開発者がターゲットシステムに全文検索機能の実現を容易にするための使いやすいツールキットを提供するように設計されています。

3.5。  シナリオ全文検索

大量のデータについては、データ構造が固定されていないデータは、百度、Googleや他の検索エンジン、検索フォーラム局として全文検索を、検索電気の供給業者のウェブサイト内を検索し、他のステーションに使用することができます。

 

4.  Luceneのフルテキスト検索処理

4.1。  索引付けと検索フローチャート

 

 

インデックス処理のための緑1、オリジナルコンテンツのインデックスは、インデックスを構築するためのライブラリを検索し、インデックス作成プロセスは、次のとおりです。

それは、収集した文書の内容A A Aは、索引付けされたドキュメントà文書分析文書を作成し、検索したオリジナルコンテンツを決定することであり、

図2は、赤色、検索処理は、検索処理の検索インデックスデータベースの内容が含まれていることを示しています。

インデックスライブラリ検索àのレンダリングからの検索結果は、検索インタフェースを介して検索を実行するクエリを作成するために、ユーザÂÂ

4.2。  インデックスを作成します

インデックスを検索するドキュメントのインデックス作成、文書のコンテンツのユーザーを処理するには、インデックスは、インデックスデータベース(インデックス)に格納されます。

ここでは、文書を検索したい場合の説明、ディスク上のテキストファイルです:ファイルは、インデックスファイル名とファイルの内容を作成するためにここに出ている見つけるためのキーワードを含む任意のファイル名やファイルの内容。

4.2.1。  元の文書を入手するには

元の文書は、単により多くのコンテンツインデックス作成と検索です。Webページ、データベース内のデータ、インターネット上のディスク上のファイルを含むオリジナルコンテンツ。

以下に示すように、この場合に元のコンテンツは、ディスク上のファイルです。

 

 

インターネットから、データベース、ファイル・システムは、元の情報の検索を取得するための媒体を必要とし、このプロセスは情報収集で、目的は、オリジナルのコンテンツインデックスに関する情報を収集することです。

ソフトウェアは、インターネット上の情報は、多くの場合、クローラは、インターネット上のすべてのページを訪問し、また、ウェブロボットとして知られ、クローラやスパイダーと呼ばれる収集し、あなたが格納されているページのコンテンツになります。

Luceneには、情報収集クラスライブラリを提供し、あなたは次のようにクローラ情報収集、情報の収集は、オープンソースソフトウェアの数によっても達成することができ、自分自身を記述する必要はありません。

Nutchの(http://lucene.apache.org/nutch)、Nutchのは、ウェブサイトのデータを取得し、区別することができ、大規模なクローラツールを含むサブプロジェクトのapacheの、です。

jsoup(http://jsoup.org/ ),jsoup 是一款Java 的HTML解析器,可直接解析某个URL地址、HTML文本内容。它提供了一套非常省力的API,可通过DOM,CSS以及类似于jQuery的操作方法来取出和操作数据。

heritrix(http://sourceforge.net/projects/archive-crawler/files/),Heritrix 是一个由 java 开发的、开源的网络爬虫,用户可以使用它来从网上抓取想要的资源。其最出色之处在于它良好的可扩展性,方便用户实现自己的抓取逻辑。

本案例我们要获取磁盘上文件的内容,可以通过文件流来读取文本文件的内容,对于pdf、doc、xls等文件可通过第三方提供的解析工具读取文件内容,比如Apache POI读取doc和xls的文件内容。

 

4.2.2. 创建文档对象

 

获取原始内容的目的是为了索引,在索引前需要将原始内容创建成文档(Document),文档中包括一个一个的域(Field),域中存储内容。

 

这里我们可以将磁盘上的一个文件当成一个document,Document中包括一些Field(file_name文件名称、file_path文件路径、file_size文件大小、file_content文件内容),如下图:

 

注意:每个Document可以有多个Field,不同的Document可以有不同的Field,同一个Document可以有相同的Field(域名和域值都相同) 

每个文档都有一个唯一的编号,就是文档id。

 

4.2.3. 分析文档

 

将原始内容创建为包含域(Field)的文档(document),需要再对域中的内容进行分析,分析的过程是经过对原始文档提取单词、将字母转为小写、去除标点符号、去除停用词等过程生成最终的语汇单元,可以将语汇单元理解为一个一个的单词。

 

比如下边的文档经过分析如下:

 

原文档内容:

Lucene is a Java full-text search engine.  Lucene is not a complete

application, but rather a code library and API that can easily be used

to add search capabilities to applications.

分析后得到的语汇单元:

lucene、java、full、search、engine。。。。

每个单词叫做一个Term,不同的域中拆分出来的相同的单词是不同的term。term中包含两部分一部分是文档的域名,另一部分是单词的内容。

例如:文件名中包含apache和文件内容中包含的apache是不同的term。

4.2.4. 创建索引

对所有文档分析得出的语汇单元进行索引,索引的目的是为了搜索,最终要实现只搜索被索引的语汇单元从而找到Document(文档)。

 

 

 一个索引可能对应多个文档

注意:创建索引是对语汇单元索引,通过词语找文档,这种索引的结构叫倒排索引结构

传统方法是根据文件找到该文件的内容,在文件内容中匹配搜索关键字,这种方法是顺序扫描方法,数据量大、搜索慢。

倒排索引结构是根据内容(词语)找文档,如下图:

 

 

倒排索引结构也叫反向索引结构,包括索引和文档两部分,索引即词汇表,它的规模较小,而文档集合较大。

4.3. 查询索引

查询索引也是搜索的过程。搜索就是用户输入关键字,从索引(index)中进行搜索的过程。根据关键字搜索索引,根据索引找到对应的文档,从而找到要搜索的内容(这里指磁盘上的文件)。

4.3.1. 用户查询接口

全文检索系统提供用户搜索的界面供用户提交搜索的关键字,搜索完成展示搜索结果。

比如:

 

 

Lucene不提供制作用户搜索界面的功能,需要根据自己的需求开发搜索界面。

4.3.2. 创建查询

用户输入查询关键字执行搜索之前需要先构建一个查询对象,查询对象中可以指定查询要搜索的Field文档域、查询关键字等,查询对象会生成具体的查询语法,

例如:

语法 “fileName:lucene”表示要搜索Field域的内容为“lucene”的文档

4.3.3. 执行查询

搜索索引过程:

根据查询语法在倒排索引词典表中分别找出对应搜索词的索引,从而找到索引所链接的文档链表。

比如搜索语法为“fileName:lucene”表示搜索出fileName域中包含Lucene的文档。

搜索过程就是在索引上查找域为fileName,并且关键字为Lucene的term,并根据term找到文档id列表。

 

 

4.3.4. 渲染结果

以一个友好的界面将查询结果展示给用户,用户根据搜索结果找自己想要的信息,为了帮助用户很快找到自己的结果,提供了很多展示的效果,比如搜索结果中将关键字高亮显示,百度提供的快照等。

 

 

5. 配置开发环境

5.1. Lucene下载

Lucene是开发全文检索功能的工具包,从官方网站下载Lucene4.10.3,并解压。

官方网站:http://lucene.apache.org/ 

版本:lucene4.10.3

Jdk要求:1.7以上

IDE:Eclipse

 

5.2. 使用的jar包

 

Lucene包:

 

lucene-core-4.10.3.jar

 

lucene-analyzers-common-4.10.3.jar

 

lucene-queryparser-4.10.3.jar

 

其它包:

 

commons-io-2.4.jar

 

junit-4.9.jar

6. 功能一:创建索引库

6.1. 实现步骤

第一步:创建一个java工程,新建一个文件夹lib,并导入jar包,添加到工作路径去。

 

第二步:新建一个测试类,添加测试方法

第三步:创建一个indexwriter对象。

 

1)指定索引库的存放位置Directory对象

 

2)指定一个分析器,对文档内容进行分析。

第四步:创建document对象。

第五步:创建field对象,将field添加到document对象中。

 

第六步:使用indexwriter对象将document对象写入索引库,此过程进行索引创建。并将索引和document对象写入索引库。

 

第七步:关闭IndexWriter对象。

 

6.2. Field域的属性

是否分析:是否对域的内容进行分词处理。前提是我们要对域的内容进行查询。

是否索引:将Field分析后的词或整个Field值进行索引,只有索引方可搜索到。

比如:商品名称、商品简介分析后进行索引,订单号、身份证号不用分析但也要索引,这些将来都要作为查询条件。

是否存储:将Field值存储在文档中,存储在文档中的Field才可以从Document中获取

比如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。

是否存储的标准:是否要将内容展示给用户

Field类

数据类型

Analyzed

是否分析

Indexed

是否索引

Stored

是否存储

说明

StringField(FieldName, FieldValue,Store.YES))

字符串

N

Y

Y或N

这个Field用来构建一个字符串Field,但是不会进行分析,会将整个串存储在索引中,比如(订单号,姓名等)

是否存储在文档中用Store.YES或Store.NO决定

LongField(FieldName, FieldValue,Store.YES)

Long型

Y

Y

Y或N

这个Field用来构建一个Long数字型Field,进行分析和索引,比如(价格)

是否存储在文档中用Store.YES或Store.NO决定

StoredField(FieldName, FieldValue) 

重载方法,支持多种类型

N

N

Y

这个Field用来构建不同类型Field

不分析,不索引,但要Field存储在文档中

TextField(FieldName, FieldValue, Store.NO)

TextField(FieldName, reader)

 

字符串

Y

Y

Y或N

如果是一个Reader, lucene猜测内容比较多,会采用Unstored的策略.

6.3. 代码实现

 

 

 

 
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.LongField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

public class FirstLucene {
    
    @Test
    public void testIndex() throws Exception{
        //创建一个indexwriter对象
        Directory directory=FSDirectory.open(new File("F:\\time"));//索引库
        Analyzer analyzer=new StandardAnalyzer();//官方分析器
        IndexWriterConfig config=new IndexWriterConfig(Version.LATEST, analyzer);
        IndexWriter iw=new IndexWriter(directory, config);
        //创建field对象,并添加到docement对象中
        File f=new File("F:\\source");
        File[] listFiles = f.listFiles();
        for (File file : listFiles) {
            //创建docement对象
            Document document=new Document();
            String file_name=file.getName();
            Field fileNameField=new TextField("fileName",file_name,Store.YES);
            long file_size=FileUtils.sizeOf(file);
            Field fileSizeField=new LongField("fileSize",file_size, Store.YES);
            String file_path=file.getPath();
            Field filePathField=new StoredField("filePath",file_path);
            String file_content=FileUtils.readFileToString(file);
            Field fileContentField=new TextField("fileContent",file_content,Store.YES);
            
            document.add(fileNameField);
            document.add(fileSizeField);
            document.add(filePathField);
            document.add(fileContentField);
            //使用indexwriter对象将document对象写入索引库
            iw.addDocument(document);
        }
            //关闭IndexWriter对象
            iw.close();
    }
}
 

 

6.4. 使用Luke工具查看索引文件

启动后,填入我们的索引路径即可

 

 

7. 功能二:查询索引

7.1. 实现步骤

第一步:创建一个Directory对象,也就是索引库存放的位置。

第二步:创建一个indexReader对象,需要指定Directory对象。

第三步:创建一个indexsearcher对象,需要指定IndexReader对象

第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。

第五步:执行查询。

第六步:返回查询结果。遍历查询结果并输出。

第七步:关闭IndexReader对象

7.2. IndexSearcher搜索方法

 

方法

说明

indexSearcher.search(query, n)

根据Query搜索,返回评分最高的n条记录

indexSearcher.search(query, filter, n)

根据Query搜索,添加过滤策略,返回评分最高的n条记录

indexSearcher.search(query, n, sort)

根据Query搜索,添加排序策略,返回评分最高的n条记录

indexSearcher.search(booleanQuery, filter, n, sort)

根据Query搜索,添加过滤策略,添加排序策略,返回评分最高的n条记录

7.3. 代码实现

 
    //搜索索引
    @Test
    public void testSearch() throws Exception{
        //创建一个Directory对象,也就是索引库存放的位置。
        Directory directory=FSDirectory.open(new File("F:\\time"));
        //创建一个indexReader对象,需要指定Directory对象。
        IndexReader ir=DirectoryReader.open(directory);
        //创建一个indexsearcher对象,需要指定IndexReader对象
        IndexSearcher indexsearcher=new IndexSearcher(ir);
        //创建一个TermQuery对象,指定查询的域和查询的关键词。
        Query query=new TermQuery(new Term("fileName","notice.txt"));
        //执行查询。
        TopDocs topDocs = indexsearcher.search(query, 2);
        //返回查询结果。遍历查询结果并输出。
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;//文档id
        for (ScoreDoc scoreDoc : scoreDocs) {
            int doc = scoreDoc.doc;
            Document document = indexsearcher.doc(doc);//获取文档
            String fileName = document.get("fileName");
            System.out.println(fileName);
            String fileContent = document.get("fileContent");
            System.out.println(fileContent);
            String fileSize= document.get("fileSize");
            System.out.println(fileSize);
            String filePath = document.get("filePath");
            System.out.println(filePath);
            System.out.println("-----------------------------");
        }
        //关闭IndexReader对象
        ir.close();
    }
 

8. 功能三:支持中文分词

8.1. 分析器(Analyzer)的执行过程

如下图是语汇单元的生成过程:

 

 

从一个Reader字符流开始,创建一个基于Reader的Tokenizer分词器,经过三个TokenFilter生成语汇单元Tokens。

要看分析器的分析效果,只需要看Tokenstream中的内容就可以了。每个分析器都有一个方法tokenStream,返回一个tokenStream对象。

 

8.2. 中文分析器

 

8.2.1. Lucene自带中文分词器

 

l StandardAnalyzer:

 

单字分词:就是按照中文一个字一个字地进行分词。如:“我爱中国”,
效果:“我”、“爱”、“中”、“国”。

 

l CJKAnalyzer

 

二分法分词:按两个字进行切分。如:“我是中国人”,效果:“我是”、“是中”、“中国”“国人”。

 

上边两个分词器无法满足需求。

 

l SmartChineseAnalyzer

 

对中文支持较好,但扩展性差,扩展词库,禁用词库和同义词库等不好处理

8.2.2. 第三方中文分析器

  • IK-analyzer: 最新版在https://code.google.com/p/ik-analyzer/上,支持Lucene 4.10从2006年12月推出1.0版开始, IKAnalyzer已经推出了4个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。从3.0版本开 始,IK发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。在2012版本中,IK实现了简单的分词 歧义排除算法,标志着IK分词器从单纯的词典分词向模拟语义分词衍化。 但是也就是2012年12月后没有在更新。

8.2.3. IKAnalyzer

 

 

使用方法:

第一步:把jar包添加到工程中

IKAnalyzer2012FF_u1.jar

第二步:把配置文件和扩展词典和停用词词典添加到classpath下

 

 

测试

 
    @Test
    public void testTokenStream() throws Exception {
        // 创建一个标准分析器对象
        Analyzer analyzer = new IKAnalyzer();
        // 获得tokenStream对象
        // 第一个参数:域名,可以随便给一个
        // 第二个参数:要分析的文本内容
        TokenStream tokenStream = analyzer.tokenStream("test","高富帅可以用二维表结构来逻辑表达实现的数据");
        // 添加一个引用,可以获得每个关键词
        CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
        // 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置
        OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class);
        // 将指针调整到列表的头部
        tokenStream.reset();
        // 遍历关键词列表,通过incrementToken方法判断列表是否结束
        while (tokenStream.incrementToken()) {
            // 关键词的起始位置
            System.out.println("start->" + offsetAttribute.startOffset());
            // 取关键词
            System.out.println(charTermAttribute);
            // 结束位置
            System.out.println("end->" + offsetAttribute.endOffset());
        }
        tokenStream.close();
    }
 

 

https://img2018.cnblogs.com/blog/1453965/201809/1453965-20180915154554817-409496595.png

ext.dic里面保留要的字段

stopword.dic保留不要的字段

8.3. Analyzer使用时机

输入关键字进行搜索,当需要让该关键字与文档域内容所包含的词进行匹配时需要对文档域内容进行分析,需要经过Analyzer分析器处理生成语汇单元(Token)。分析器分析的对象是文档中的Field域。当Field的属性tokenized(是否分词)为true时会对Field值进行分析,如下图: 

 

 

 

对于一些Field可以不用分析:

1、不作为查询条件的内容,比如文件路径

2、不是匹配内容中的词而匹配Field的整体内容,比如订单号、身份证号等。

注意:搜索使用的分析器要和索引使用的分析器一致。

9. 功能四:索引库的维护

新建一个class,用于测试

9.1. 索引库删除

9.1.1. 删除全部

 
package com.it.lucene;

import java.io.File;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.junit.Test;

public class LuceneManager {
    public IndexWriter getIndexWriter() throws Exception{
          //创建一个indexwriter对象
        Directory directory=FSDirectory.open(new File("F:\\time"));//索引库
        Analyzer analyzer=new StandardAnalyzer();//官方分析器
        IndexWriterConfig config=new IndexWriterConfig(Version.LATEST, analyzer);
        return new IndexWriter(directory, config);
    }
    //全删除
    @Test
    public void testAllDelete() throws Exception{
        IndexWriter indexWriter=getIndexWriter();
        indexWriter.deleteAll();
        indexWriter.close();
    }
}
 

9.1.2. 指定查询条件删除

 
//根据条件删除
    @Test
    public void testDelete() throws Exception{
        IndexWriter indexWriter=getIndexWriter();
        Query query=new TermQuery(new Term("fileName","notice.txt"));
        indexWriter.deleteDocuments(query);
        indexWriter.close();
    }
 

9.2. 索引库修改

原理就是先删除后添加。

 
    //修改
    @Test
    public void testUpdate() throws Exception{
        IndexWriter indexWriter=getIndexWriter();
        Document doc=new Document();
        doc.add(new TextField("fileN","测试文件名",Store.YES));
        indexWriter.updateDocument(new Term("fileName","notice"),doc,new IKAnalyzer());
        indexWriter.close();
    }
 

10. Lucene索引库查询(重点)

对要搜索的信息创建Query查询对象,Lucene会根据Query查询对象生成最终的查询语法,类似关系数据库Sql语法一样Lucene也有自己的查询语法,比如:“name:lucene”表示查询Field的name为“lucene”的文档信息。

掌握以下一种即可

可通过两种方法创建查询对象:

1)使用Lucene提供Query子类

Query是一个抽象类,lucene提供了很多查询对象,比如TermQuery项精确查询,NumericRangeQuery数字范围查询等。

如下代码:

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

2)使用QueryParse解析查询表达式

QueryParse会将用户输入的查询表达式解析成Query对象实例。

如下代码:

QueryParser queryParser = new QueryParser("name", new IKAnalyzer());

Query query = queryParser.parse("name:lucene");

10.1. 使用query的子类查询

 

10.1.1. MatchAllDocsQuery

 

使用MatchAllDocsQuery查询索引目录中的所有文档

 
public IndexSearcher getIndexSearcher() throws Exception{
          //创建一个Directory对象,也就是索引库存放的位置。
        Directory directory=FSDirectory.open(new File("F:\\time"));
        //创建一个indexReader对象,需要指定Directory对象。
        IndexReader ir=DirectoryReader.open(directory);
        //创建一个indexsearcher对象,需要指定IndexReader对象
        return new IndexSearcher(ir);
    }
    
    //执行查询结果
    public static void printResult(IndexSearcher indexsearcher,Query query) throws Exception{    
        //执行查询。
        TopDocs topDocs = indexsearcher.search(query, 2);
        //返回查询结果。遍历查询结果并输出。
        ScoreDoc[] scoreDocs = topDocs.scoreDocs;//文档id
        for (ScoreDoc scoreDoc : scoreDocs) {
            int doc = scoreDoc.doc;
            Document document = indexsearcher.doc(doc);//获取文档
            String fileName = document.get("fileName");
            System.out.println(fileName);
            String fileContent = document.get("fileContent");
            System.out.println(fileContent);
            String fileSize= document.get("fileSize");
            System.out.println(fileSize);
            String filePath = document.get("filePath");
            System.out.println(filePath);
            System.out.println("-----------------------------");
        }
    } 
    //查询所有
    @Test
    public void testMatchAllDocsQuery() throws Exception{
        IndexSearcher indexSearcher=getIndexSearcher();
        Query query=new MatchAllDocsQuery();
        printResult(indexSearcher,query);
        indexSearcher.getIndexReader().close();
    }
 

10.1.2. TermQuery

TermQuery,通过项查询,TermQuery不使用分析器所以建议匹配不分词的Field域查询,比如订单号、分类ID号等。

指定要查询的域和要查询的关键词。

 
  //使用Termquery查询
    @Test
    public void testTermQuery() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //创建查询对象
        Query query = new TermQuery(new Term("fileName", "notice"));
        //执行查询
        TopDocs topDocs = indexSearcher.search(query, 10);
        //共查询到的document个数
        System.out.println("查询结果总数量:" + topDocs.totalHits);
    }
 

10.1.3. NumericRangeQuery

可以根据数值范围查询。

 
    //根据数值范围查询
    @Test
    public void testNumericRangeQuery() throws Exception{
        IndexSearcher indexSearcher=getIndexSearcher();
        Query query=NumericRangeQuery.newLongRange("fileSize", 1L, 20000L, true, true);
        printResult(indexSearcher,query);
        indexSearcher.getIndexReader().close();
    }
 

10.1.4. BooleanQuery

可以组合查询条件。

 
  //组合条件查询
      @Test
      public void testBooleanQuery() throws Exception {
          IndexSearcher indexSearcher = getIndexSearcher();
          //创建一个布尔查询对象
          BooleanQuery query = new BooleanQuery();
          //创建第一个查询条件
          Query query1 = new TermQuery(new Term("fileName", "notice"));
          Query query2 = new TermQuery(new Term("fileContent", "has"));
          //组合查询条件
          query.add(query1, Occur.SHOULD);
          query.add(query2, Occur.SHOULD);
          //执行查询
          printResult(indexSearcher,query);
      }
 

Occur.MUST:必须满足此条件,相当于and

Occur.SHOULD:应该满足,但是不满足也可以,相当于or

Occur.MUST_NOT:必须不满足。相当于not

 

10.2. 使用queryparser查询

 

通过QueryParser也可以创建Query,QueryParser提供一个Parse方法,此方法可以直接根据查询语法来查询。Query对象执行的查询语法可通过System.out.println(query);查询。

 

需要使用到分析器。建议创建索引时使用的分析器和查询索引时使用的分析器要一致。

 

10.2.1. QueryParser

 
//条件解析的对象查询     
@Test public void testQueryParser() throws Exception { IndexSearcher indexSearcher = getIndexSearcher(); //创建queryparser对象 //第一个参数默认搜索的域 //第二个参数就是分析器对象 QueryParser queryParser = new QueryParser("fileName",new IKAnalyzer()); //*:* 域:值 Query query = queryParser.parse("notice"); //执行查询 printResult(indexSearcher,query); }
 

查询语法

1、基础的查询语法,关键词查询:

域名+“:”+搜索的关键字

例如:content:java

2、范围查询

域名+“:”+[最小值 TO 最大值]

例如:size:[1 TO 1000]

范围查询在lucene中支持数值类型,不支持字符串类型。在solr中支持字符串类型。

3、组合条件查询

1)+条件1 +条件2:两个条件之间是并且的关系and

例如:+filename:apache +content:apache

2)+条件1 条件2:必须满足第一个条件,应该满足第二个条件

例如:+filename:apache content:apache

3)条件1 条件2:两个条件满足其一即可。

例如:filename:apache content:apache

4)-条件1 条件2:必须不满足条件1,要满足条件2

例如:-filename:apache content:apache

Occur.MUST 查询条件必须满足,相当于and

+(加号)

Occur.SHOULD 查询条件可选,相当于or

 

空(不用符号)

Occur.MUST_NOT 查询条件不能满足,相当于not非

-(减号)

 

第二种写法:

条件1 AND 条件2

条件1 OR 条件2

条件1 NOT 条件2

 

 

10.2.2. MultiFieldQueryParser

 

可以指定多个默认搜索域

 
     //条件解析的对象查询 多个默认域
      @Test
    public void testMultiFiledQueryParser() throws Exception {
        IndexSearcher indexSearcher = getIndexSearcher();
        //可以指定默认搜索的域是多个
        String[] fields = {"fileName", "fileContent"};
        //创建一个MulitFiledQueryParser对象
        MultiFieldQueryParser queryParser = new MultiFieldQueryParser(fields, new IKAnalyzer());
        Query query = queryParser.parse("java AND apache");
        System.out.println(query);
        //执行查询
        printResult(indexSearcher,query);
        
    }