Lucene学习:lucene查询

1.1. Lucene查询

在学习Lucene的查询方法前,先了解一下下面几个类:

1.1.1. Query

封装某种查询类型的具体子类,配置查询的查询条件。Query实例将被传递给IndexSearchersearch方法。下面是常用的Query子类:

l 通过项进行搜索 TermQuery类

l 在指定的项范围内搜索 TermRangeQuery类

l 通过字符串搜索 PrefixQuery类

l 组合查询 BooleanQuery类

l 通过短语搜索 PhraseQuery类

l 通配符查询 WildcardQuery类

l 搜索类似项 FuzzyQuery类

l 匹配所有文档 MatchAllDocsQuery类

l 不匹配文档 MatchNoDocsQuery类

l 解析查询表达式 QueryParser类

l 多短语查询 MultiPhraseQuery类

l 查询所有 MatchAllDocsQuery类

l 不匹配所有文档 MatchNoDocsQuery类

1.1.2. QueryParser

将用户输入的可读的查询表达式处理成具体的Query对象

示例:

 1 @Test
 2 
 3     public void testQueryParser() throws ParseException, IOException {
 4 
 5         //使用WhitespaceAnalyzer分析器不会忽略大小写,也就是说大小写敏感
 6 
 7         QueryParser queryParser = new QueryParser("bookcontent", new IKAnalyzer());
 8 
 9         Query query = queryParser.parse("2018");
10 
11         IndexSearcher searcher = getIndexSearcher();
12 
13         TopDocs topDocs = searcher.search(query, 10);
14 
15         
16 
17         // 返回查询结果。遍历查询结果并输出。
18 
19 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
20 
21 for (ScoreDoc scoreDoc : scoreDocs) {
22 
23 int doc = scoreDoc.doc;
24 
25 Document document = searcher.doc(doc);  
26 
27 // 打印content字段的值
28 
29 System.out.println("bookid: "+document.get("bookid"));
30 
31 System.out.println("bookname: "+document.get("bookname"));
32 
33 System.out.println("booktype: "+document.get("booktype"));
34 
35 System.out.println("bookcontent: "+document.get("bookcontent"));
36 
37 }   
38 
39 }

1.1.3. MultiFieldQueryParser

 1 /**
 2 
 3      * 传统解析器-多默认字段
 4 
 5      * B. 基于新的 flexible 框架的解析器:StandardQueryParser
 6 
 7      */
 8 
 9     @Test
10 
11     public void MultiFieldQueryParser() {
12 
13      try {    
14 
15      String[] multiDefaultFields = { "bookname", "booktype", "bookcontent" };
16 
17      org.apache.lucene.queryparser.classic.MultiFieldQueryParser multiFieldQueryParser = new org.apache.lucene.queryparser.classic.MultiFieldQueryParser(
18 
19              multiDefaultFields, new IKAnalyzer());
20 
21      // 设置默认的组合操作,默认是 OR
22 
23      multiFieldQueryParser.setDefaultOperator(Operator.OR);
24 
25      Query query = multiFieldQueryParser.parse("西游记》又称央视86版《西游记》,改编自明12345678901");
26 
27 doSearch(query);
28 
29 } catch (Exception e) {
30 
31 e.printStackTrace();
32 
33 }
34 
35     }

1.1.4. TermQuery

 1 /**
 2 
 3      *  词项查询
 4 
 5      *  最基本、最常用的查询。用来查询指定字段包含指定词项的文档。
 6 
 7      */
 8 
 9     @Test
10 
11     public void termQuery() {
12 
13      try {
14 
15      IndexSearcher searcher = getIndexSearcher();
16 
17  
18 
19 TermQuery tq = new TermQuery(new Term("bookname", "西游记"));
20 
21         TopDocs topDocs = searcher.search(tq, 10);
22 
23         printTopDocs(topDocs);
24 
25 } catch (Exception e) {
26 
27 e.printStackTrace();
28 
29 }
30 
31     }

1.1.5. booleanQuery

 1 /**
 2 
 3      * 布尔查询
 4 
 5      * 搜索的条件往往是多个的,如要查询名称包含“电脑” 或 “thinkpad”的商品,就需要两个词项查询做或合并。布尔查询就是用来组合多个子查询的。
 6 
 7      * 每个子查询称为布尔字句 BooleanClause,布尔字句自身也可以是组合的。 组合关系支持如下四种:
 8 
 9      * Occur.SHOULD 或
10 
11      * Occur.MUST 且
12 
13      * Occur.MUST_NOT 且非
14 
15      * Occur.FILTER 同 MUST,但该字句不参与评分
16 
17      * 布尔查询默认的最大字句数为1024,在将通配符查询这样的查询rewriter为布尔查询时,往往会产生很多的字句,可能抛出TooManyClauses 异常。
18 
19      * 可通过BooleanQuery.setMaxClauseCount(int)设置最大字句数。
20 
21      */
22 
23     @Test
24 
25     public void booleanQuery() {
26 
27      try {
28 
29 // 创建一个indexsearcher对象
30 
31 IndexSearcher searcher = getIndexSearcher();
32 
33  
34 
35 BooleanQuery.Builder builder = new BooleanQuery.Builder();
36 
37 // 书内容
38 
39 QueryParser queryParser = new QueryParser("bookcontent", new IKAnalyzer());
40 
41     Query query1 = queryParser.parse("西游记");
42 
43     builder.add(query1, Occur.MUST);
44 
45     
46 
47     // 书名称
48 
49     Query qymc = new FuzzyQuery(new Term("bookname", "西游记"));
50 
51 builder.add(qymc, Occur.MUST);
52 
53     
54 
55 // 书类型
56 
57 Query gmsfhm = new TermQuery(new Term("booktype", "小说"));
58 
59 builder.add(gmsfhm, Occur.MUST);
60 
61     
62 
63 BooleanQuery booleanQuery = builder.build();
64 
65  
66 
67         TopDocs topDocs = searcher.search(booleanQuery, 10);
68 
69         printTopDocs(topDocs);
70 
71 } catch (Exception e) {
72 
73 e.printStackTrace();
74 
75 }
76 
77     }

1.1.5.1. Occur

Occur是用来决定各个条件的逻辑关系,具体如下:

l Occur.SHOULD

l Occur.MUST

l Occur.MUST_NOT 且非

l Occur.FILTER MUST,但该字句不参与评分

而这些逻辑组合之间也有要关注的地方(下面几点关注一下即可,跟版本有关,在8.1.0的版本中是直接意思,并没有出现下面的情况。应该是新版已经更新,6版本之前的可以关注下面的信息。):

  1. MUST和MUST:取得连个查询子句的交集。 
  2. MUST和MUST_NOT:表示查询结果中不能包含MUST_NOT所对应得查询子句的检索结果。 
  3. SHOULD与MUST_NOT:连用时,功能同MUST和MUST_NOT。
  4. SHOULD与MUST连用时,结果为MUST子句的检索结果,但是SHOULD可影响排序。
  5. SHOULD与SHOULD:表示“或”关系,最终检索结果为所有检索子句的并集。
  6. MUST_NOT和MUST_NOT:无意义,检索无结果。

1.1.6. phraseQuery

 1 /**
 2 
 3      * 短语查询
 4 
 5      * 最常用的查询,匹配特定序列的多个词项。PhraserQuery使用一个位置移动因子(slop)来决定任意两个词项的位置可最大移动多少个位置来进行匹配,默认为0。
 6 
 7      * 有两种方式来构建对象:
 8 
 9      * 注意:所有加入的词项都匹配才算匹配(即使是你在同一位置加入多个词项)。如果需要在同一位置匹配多个同义词中的一个,适合用MultiPhraseQuery
10 
11      */
12 
13     @Test
14 
15     public void phraseQuery() {
16 
17      try {  
18 
19 PhraseQuery phraseQuery1 = new PhraseQuery("bookcontent", "根据", "明代");
20 
21  
22 
23 PhraseQuery phraseQuery2 = new PhraseQuery(0, "bookcontent", "根据", "明代");
24 
25  
26 
27 PhraseQuery phraseQuery3 = new PhraseQuery("bookcontent", "笔记本电脑", "联想");
28 
29  
30 
31 PhraseQuery phraseQuery4 = new PhraseQuery.Builder()
32 
33     .add(new Term("bookcontent", "根据"), 4)
34 
35     .add(new Term("bookcontent", "施耐"), 5).build();
36 
37 // 这两句等同
38 
39 PhraseQuery phraseQuery5 = new PhraseQuery.Builder()
40 
41     .add(new Term("bookcontent", "笔记本电脑"), 0)
42 
43     .add(new Term("bookcontent", "联想"), 1).build();
44 
45  
46 
47 doSearch(phraseQuery2);
48 
49 } catch (Exception e) {
50 
51 e.printStackTrace();
52 
53 }
54 
55     }

1.1.7. multiPhraseQuery

 1 /**
 2 
 3      * 多重短语查询
 4 
 5      * 短语查询的一种更通用的用法,支持同位置多个词的OR匹配。通过里面的Builder来构建MultiPhraseQuery:
 6 
 7      */
 8 
 9     @Test
10 
11     public void multiPhraseQuery() {
12 
13      try {  
14 
15      // 4 MultiPhraseQuery 多重短语查询
16 
17      Term[] terms = new Term[2];
18 
19      terms[0] = new Term("bookcontent", "根据");
20 
21      terms[1] = new Term("bookcontent", "根据明代");
22 
23      Term t = new Term("bookcontent", "施耐");
24 
25      MultiPhraseQuery multiPhraseQuery = new MultiPhraseQuery.Builder()
26 
27          .add(terms).add(t).build();
28 
29  
30 
31      // 对比 PhraseQuery在同位置加入多个词 ,同位置的多个词都需匹配,所以查不出。
32 
33      PhraseQuery pquery = new PhraseQuery.Builder().add(terms[0], 0)
34 
35          .add(terms[1], 0).add(t, 1).build();
36 
37  
38 
39 doSearch(multiPhraseQuery);
40 
41 } catch (Exception e) {
42 
43 e.printStackTrace();
44 
45 }
46 
47     }

1.1.8. spanNearQuery

 1 /**
 2 
 3      * 临近查询(跨度查询)
 4 
 5      * 用于更复杂的短语查询,可以指定词间位置的最大间隔跨度。通过组合一系列的SpanQuery 实例来进行查询,可以指定是否按顺序匹配、slop、gap
 6 
 7      */
 8 
 9     @Test
10 
11     public void spanNearQuery() {
12 
13      try {  
14 
15      // SpanNearQuery 临近查询
16 
17      SpanTermQuery tq1 = new SpanTermQuery(new Term("bookcontent", "中央电视台"));
18 
19      SpanTermQuery tq2 = new SpanTermQuery(new Term("bookcontent", "无锡"));
20 
21      SpanNearQuery spanNearQuery = new SpanNearQuery(
22 
23          new SpanQuery[] { tq1, tq2 }, 0, true);
24 
25  
26 
27      // SpanNearQuery 临近查询 gap slop 使用
28 
29      SpanNearQuery.Builder spanNearQueryBuilder = SpanNearQuery
30 
31          .newOrderedNearQuery("bookcontent");
32 
33      spanNearQueryBuilder.addClause(tq1).addGap(0).setSlop(1)
34 
35          .addClause(tq2);
36 
37      SpanNearQuery spanNearQuery5 = spanNearQueryBuilder.build();
38 
39 //     IndexSearcher searcher = getIndexSearcher();
40 
41 // TopDocs topDocs = searcher.search(spanNearQueryBuilder, 10);
42 
43 doSearch(spanNearQuery);
44 
45 } catch (Exception e) {
46 
47 e.printStackTrace();
48 
49 }
50 
51     }

1.1.9. termRangeQuery

 1 /**
 2 
 3      * 词项范围查询
 4 
 5      * 用于查询包含某个范围内的词项的文档,如以字母开头a到c的词项。词项在反向索引中是排序的,只需指定的开始词项、结束词项,就可以查询该范围的词项。
 6 
 7      * 如果是做数值的范围查询则用 PointRangeQuery
 8 
 9      * 参数说明:
10 
11      * 第1个参数:要查询的字段-field
12 
13      * 第2个参数::下边界词-lowerTerm
14 
15      * 第3个参数:上边界词-upperTerm
16 
17      * 第4个参数:是否包含下边界-includeLower
18 
19      * 第5个参数:是否包含上边界 includeUpper
20 
21      */
22 
23     @Test
24 
25     public void termRangeQuery() {
26 
27      try {   
28 
29      // TermRangeQuery 词项范围查询
30 
31      TermRangeQuery termRangeQuery = TermRangeQuery.newStringRange("bookcontent",
32 
33          "中央电视台", "同名小说改编", false, true);
34 
35 doSearch(termRangeQuery);
36 
37 } catch (Exception e) {
38 
39 e.printStackTrace();
40 
41 }
42 
43     }

1.1.10. prefixQuery

 1 /**
 2 
 3      * 前缀查询
 4 
 5      * PrefixQuery:前缀查询,查询包含以xxx为前缀的词项的文档,是通配符查询,如 app,实际是 app*
 6 
 7      */
 8 
 9     @Test
10 
11     public void prefixQuery() {
12 
13      try {   
14 
15      // PrefixQuery 前缀查询
16 
17      PrefixQuery prefixQuery = new PrefixQuery(new Term("bookcontent", "中国"));
18 
19 doSearch(prefixQuery);
20 
21 } catch (Exception e) {
22 
23 e.printStackTrace();
24 
25 }
26 
27 }

1.1.11. wildcardQuery

 1 /**
 2 
 3      * 通配符查询
 4 
 5      * WildcardQuery:通配符查询, *表示0个或多个字符,?表示1个字符,\是转义符。通配符查询可能会比较慢,不可以通配符开头(那样就是所有词项了)
 6 
 7      */
 8 
 9     @Test
10 
11     public void wildcardQuery() {
12 
13      try {   
14 
15      // WildcardQuery 通配符查询
16 
17      WildcardQuery wildcardQuery = new WildcardQuery(
18 
19          new Term("bookcontent", "中国*"));
20 
21 doSearch(wildcardQuery);
22 
23 } catch (Exception e) {
24 
25 e.printStackTrace();
26 
27 }
28 
29     }

1.1.12. regexpQuery

 1 /**
 2 
 3      * 正则表达式查询
 4 
 5      * RegexpQuery:正则表达式查询,词项符合某正则表达式
 6 
 7      */
 8 
 9     @Test
10 
11     public void regexpQuery() {
12 
13      try {   
14 
15      // RegexpQuery 正则表达式查询
16 
17      RegexpQuery regexpQuery = new RegexpQuery(new Term("bookcontent", "厉害.{4}"));
18 
19 doSearch(regexpQuery);
20 
21 } catch (Exception e) {
22 
23 e.printStackTrace();
24 
25 }
26 
27     }

1.1.13. fuzzyQuery

 1 /**
 2 
 3      * 模糊查询
 4 
 5      * 简单地与索引词项进行相近匹配,允许最大2个不同字符。常用于拼写错误的容错:如把 “thinkpad” 拼成 “thinkppd”或 “thinkd”,使用FuzzyQuery 仍可搜索到正确的结果。
 6 
 7      */
 8 
 9     @Test
10 
11     public void fuzzyQuery() {
12 
13      try {   
14 
15      // FuzzyQuery 模糊查询
16 
17      FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("bookcontent", "猪八戒"));
18 
19  
20 
21      FuzzyQuery fuzzyQuery2 = new FuzzyQuery(new Term("bookcontent", "thinkd"), 2);
22 
23  
24 
25      FuzzyQuery fuzzyQuery3 = new FuzzyQuery(new Term("bookcontent", "thinkpaddd"));
26 
27  
28 
29      FuzzyQuery fuzzyQuery4 = new FuzzyQuery(new Term("bookcontent", "thinkdaddd"));
30 
31 doSearch(fuzzyQuery);
32 
33 } catch (Exception e) {
34 
35 e.printStackTrace();
36 
37 }
38 
39     }

1.1.14. 高亮

 1 /**
 2 
 3      * 高亮排序查询
 4 
 5      * @throws InvalidTokenOffsetsException
 6 
 7      */
 8 
 9     private void highLightSearch(Query query) throws InvalidTokenOffsetsException {
10 
11      // 获取一个indexReader对象
12 
13 try {
14 
15 Analyzer ikanalyzer = new IKAnalyzer();
16 
17 IndexSearcher searcher = getIndexSearcher();
18 
19 //true表示降序
20 
21 //SortField.Type.SCORE  根据相关度进行排序(默认)
22 
23 //SortField.Type.DOC    根据文档编号或者说是索引顺序
24 
25 //SortField.Type.FLOAT(Long等),根据fieldName的数值类型进行排序
26 
27 SortField sortField = new SortField("bookprice",SortField.Type.INT,false);
28 
29 Sort sort = new Sort(sortField);
30 
31  
32 
33 TopDocs topDocs = searcher.search(query, 10, sort);
34 
35      System.out.println("数字查询");  
36 
37         System.out.println("命中结果数为: "+ topDocs.totalHits);
38 
39         // 返回查询结果。遍历查询结果并输出。
40 
41 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
42 
43 for (ScoreDoc scoreDoc : scoreDocs) {
44 
45 int doc = scoreDoc.doc;
46 
47 Document document = searcher.doc(doc);  
48 
49 String text = document.get("bookcontent");  
50 
51         SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");  
52 
53         Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));  
54 
55         highlighter.setTextFragmenter(new SimpleFragmenter(text.length()));  
56 
57         if (text != null) {  
58 
59             TokenStream tokenStream = ikanalyzer.tokenStream("bookcontent", new StringReader(text));  
60 
61             String highLightText = highlighter.getBestFragment(tokenStream,text);  
62 
63             System.out.println("高亮显示第 " + (doc + 1) + " 条检索结果如下所示:");  
64 
65             System.out.println("bookcontent: "+highLightText);  
66 
67         }  
68 
69  
70 
71 // 打印content字段的值
72 
73 System.out.println("bookid: "+document.get("bookid"));
74 
75 System.out.println("bookname: "+document.get("bookname"));
76 
77 System.out.println("booktype: "+document.get("booktype"));
78 
79 System.out.println("bookprice: "+document.get("bookprice"));
80 
81 System.out.println("bookdate: "+document.get("bookdate"));
82 
83 // System.out.println("bookcontent: "+document.get("bookcontent"));
84 
85 System.out.println("查询得分是: "+scoreDoc.score);
86 
87 System.out.println("--------------我是分割线------------------");
88 
89 }
90 
91 } catch (IOException e) {
92 
93 e.printStackTrace();
94 
95 }
96 
97     }

1.1.15. 排序

 1 /**
 2 
 3      * 排序查询
 4 
 5      */
 6 
 7     private void sortSearch(Query query) {
 8 
 9      // 获取一个indexReader对象
10 
11 try {
12 
13 IndexSearcher searcher = getIndexSearcher();
14 
15 //true表示降序
16 
17 //SortField.Type.SCORE  根据相关度进行排序(默认)
18 
19 //SortField.Type.DOC    根据文档编号或者说是索引顺序
20 
21 //SortField.Type.FLOAT(Long等),根据fieldName的数值类型进行排序
22 
23 SortField sortField = new SortField("bookcontent",SortField.Type.SCORE,false);
24 
25 Sort sort = new Sort(sortField);
26 
27  
28 
29 TopDocs topDocs = searcher.search(query, 10, sort);
30 
31      System.out.println("数字查询");  
32 
33         System.out.println("命中结果数为: "+ topDocs.totalHits);
34 
35         // 返回查询结果。遍历查询结果并输出。
36 
37 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
38 
39 for (ScoreDoc scoreDoc : scoreDocs) {
40 
41 int doc = scoreDoc.doc;
42 
43 Document document = searcher.doc(doc);  
44 
45 // 打印content字段的值
46 
47 System.out.println("bookid: "+document.get("bookid"));
48 
49 System.out.println("bookname: "+document.get("bookname"));
50 
51 System.out.println("booktype: "+document.get("booktype"));
52 
53 System.out.println("bookprice: "+document.get("bookprice"));
54 
55 System.out.println("bookcontent: "+document.get("bookcontent"));
56 
57 System.out.println("查询得分是: "+scoreDoc.score);
58 
59 System.out.println("--------------我是分割线------------------");
60 
61 }
62 
63 } catch (IOException e) {
64 
65 e.printStackTrace();
66 
67 }
68 
69     }

1.1.15.1. SortField

l SortField.Type.SCORE  根据相关度进行排序(默认)

l SortField.Type.DOC    根据文档编号或者说是索引顺序

l SortField.Type.FLOAT(Long等),根据fieldName的数值类型进行排序

1.1.16. 代码集合

  1 import java.io.IOException;
  2 import java.io.StringReader;
  3 import org.apache.lucene.analysis.Analyzer;
  4 import org.apache.lucene.analysis.TokenStream;
  5 import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
  6 import org.apache.lucene.analysis.standard.StandardAnalyzer;
  7 import org.apache.lucene.document.Document;
  8 import org.apache.lucene.document.Field;
  9 import org.apache.lucene.document.IntPoint;
 10 import org.apache.lucene.document.NumericDocValuesField;
 11 import org.apache.lucene.document.StoredField;
 12 import org.apache.lucene.document.StringField;
 13 import org.apache.lucene.document.TextField;
 14 import org.apache.lucene.index.DirectoryReader;
 15 import org.apache.lucene.index.IndexWriter;
 16 import org.apache.lucene.index.IndexWriterConfig;
 17 import org.apache.lucene.index.Term;
 18 import org.apache.lucene.queryparser.classic.ParseException;
 19 import org.apache.lucene.queryparser.classic.QueryParser;
 20 import org.apache.lucene.queryparser.classic.QueryParser.Operator;
 21 import org.apache.lucene.queryparser.simple.SimpleQueryParser;
 22 import org.apache.lucene.search.BooleanQuery;
 23 import org.apache.lucene.search.FuzzyQuery;
 24 import org.apache.lucene.search.IndexSearcher;
 25 import org.apache.lucene.search.MultiPhraseQuery;
 26 import org.apache.lucene.search.PhraseQuery;
 27 import org.apache.lucene.search.PrefixQuery;
 28 import org.apache.lucene.search.Query;
 29 import org.apache.lucene.search.RegexpQuery;
 30 import org.apache.lucene.search.ScoreDoc;
 31 import org.apache.lucene.search.Sort;
 32 import org.apache.lucene.search.SortField;
 33 import org.apache.lucene.search.TermQuery;
 34 import org.apache.lucene.search.TermRangeQuery;
 35 import org.apache.lucene.search.TopDocs;
 36 import org.apache.lucene.search.WildcardQuery;
 37 import org.apache.lucene.search.highlight.Highlighter;
 38 import org.apache.lucene.search.highlight.InvalidTokenOffsetsException;
 39 import org.apache.lucene.search.highlight.QueryScorer;
 40 import org.apache.lucene.search.highlight.SimpleFragmenter;
 41 import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
 42 import org.apache.lucene.search.spans.SpanNearQuery;
 43 import org.apache.lucene.search.spans.SpanQuery;
 44 import org.apache.lucene.search.spans.SpanTermQuery;
 45 import org.apache.lucene.search.BooleanClause.Occur;
 46 import org.apache.lucene.store.Directory;
 47 import org.apache.lucene.store.RAMDirectory;
 48 import org.junit.Before;
 49 import org.junit.Test;
 50 import org.wltea.analyzer.lucene.IKAnalyzer;
 51 public class FullTextRetrieval {
 52 private Directory directory = new RAMDirectory();
 53     private IndexWriterConfig indexWriterConfig = new IndexWriterConfig(new IKAnalyzer());
 54     private IndexWriter indexWriter;
 55  @Before
 56     public void createIndex() {
 57         try {
 58             indexWriter = new IndexWriter(directory, indexWriterConfig);
 59                 Document doc = new Document();
 60                 // 书主键
 61      doc = new Document();
 62          doc.add(new StringField("bookid", "1345678", Field.Store.YES));
 63          // 书名
 64          doc.add(new StringField("bookname", "西游记", Field.Store.YES));  
 65          // 书的类型
 66          doc.add(new StringField("booktype", "小说", Field.Store.YES));
 67          // 书的价格
 68          doc.add(new NumericDocValuesField("bookprice", 123));  
 69          // 书的日期年份
 70          Field intPoint = new IntPoint("bookdate", 1066);
 71          doc.add(intPoint);
 72          intPoint = new StoredField("bookdate", 1066);
 73          doc.add(intPoint);
 74 //         doc.add(new NumericDocValuesField("bookdate", 123));  
 75          // 书的内容
 76          doc.add(new TextField("bookcontent", "《西游记》又称央视86版《西游记》,改编自明代小说家吴承恩同名文学古典名著。是由中央电视台、中国电视剧制作中心出品的一部25集古装神话剧。由杨洁执导,戴英禄,杨洁,邹忆青共同编剧,六小龄童、徐少华、迟重瑞、汪粤、马德华、闫怀礼等主演,李世宏、李扬、张云明、里坡等担任主要配音。 [1] \r\n" +
 77 
 78           "该剧讲述的是孙悟空、猪八戒、沙僧辅保大唐高僧玄奘去西天取经,师徒四人一路抢滩涉险,降妖伏怪,历经八十一难,取回真经,终修正果的故事。\r\n" +
 79 
 80           "《西游记》于1982年7月3日开机,同年10月1日首播试集《除妖乌鸡国》。1986年春节在央视首播前11集,1988年25集播出。\r\n" +
 81 
 82           "1986年春节一经播出,轰动全国,老少皆宜,获得了极高评价,造就了89.4%的收视率神话,至今仍是寒暑假被重播最多的电视剧,重播次数超过3000次,依然百看不厌,成为一部公认的无法超越的经典。", Field.Store.YES));
 83 
 84          // 添加文档
 85          indexWriter.addDocument(doc);
 86          // 书主键
 87       doc = new Document();
 88           doc.add(new StringField("bookid", "12345678", Field.Store.YES));
 89           // 书名
 90           doc.add(new StringField("bookname", "水浒传", Field.Store.YES));  
 91           // 书的类型
 92           doc.add(new StringField("booktype", "小说", Field.Store.YES));  
 93           // 书的价格
 94          doc.add(new NumericDocValuesField("bookprice", 432));  
 95          // 书的日期年份
 96          Field intPoint1 = new IntPoint("bookdate", 1666);
 97          doc.add(intPoint1);
 98          intPoint = new StoredField("bookdate", 1666);
 99          doc.add(intPoint1);
100           // 书的内容
101           doc.add(new TextField("bookcontent", "中国大陆,中央电视台无锡太湖影视城 43集\r\n" +
102            "《水浒传》是由中央电视台与中国电视剧制作中心联合出品的43集电视连续剧,根据明代施耐庵的同名小说改编。 [1]  由张绍林执导,杨争光 、冉平改编,李雪健、周野芒、臧金生、丁海峰、赵小锐领衔主演。\r\n" +
103 
104            "该剧讲述的是宋朝徽宗时皇帝昏庸、奸臣当道、官府腐败、贪官污吏陷害忠良,弄得民不聊生,许多正直善良的人被官府逼得无路可走,被迫奋起反抗,最终108条好汉聚义梁山泊,但随后宋江对朝廷的投降使得一场轰轰烈烈的农民起义最后走向失败的故事。 [2] \r\n" +
105            "《水浒传》于1998年1月8日在中央电视台一套首播。 [3] \r\n" +
106            "2018年9月8日,9月15日,9月22日,央视四台《中国文艺》“向经典致敬”栏目播出《水浒传》20周年聚首专题节目", Field.Store.YES));
107                 indexWriter.addDocument(doc);
108             indexWriter.close();
109         } catch (IOException e) {
110             e.printStackTrace();
111         }
112     }
113 private IndexSearcher getIndexSearcher() throws IOException {
114         return new IndexSearcher(DirectoryReader.open(directory));
115     }
116 
117  /**
118      * 全文检索
119      * @throws ParseException
120      * @throws IOException
121      */
122     @Test
123     public void testQueryParser() throws ParseException, IOException {
124         //使用WhitespaceAnalyzer分析器不会忽略大小写,也就是说大小写敏感
125         QueryParser queryParser = new QueryParser("bookcontent", new IKAnalyzer());
126         Query query = queryParser.parse("2018");
127         IndexSearcher searcher = getIndexSearcher();
128         TopDocs topDocs = searcher.search(query, 10);
129         // 返回查询结果。遍历查询结果并输出。
130 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
131 
132 for (ScoreDoc scoreDoc : scoreDocs) {
133 
134 int doc = scoreDoc.doc;
135 
136 Document document = searcher.doc(doc);  
137 
138 // 打印content字段的值
139 
140 System.out.println("bookid: "+document.get("bookid"));
141 
142 System.out.println("bookname: "+document.get("bookname"));
143 
144 System.out.println("booktype: "+document.get("booktype"));
145 
146 System.out.println("bookcontent: "+document.get("bookcontent"));
147 
148 }   
149     }
150     /**
151      *  词项查询
152      *  最基本、最常用的查询。用来查询指定字段包含指定词项的文档。
153      */
154     @Test
155     public void termQuery() {
156      try {
157      IndexSearcher searcher = getIndexSearcher();
158 TermQuery tq = new TermQuery(new Term("bookname", "西游记"));
159         TopDocs topDocs = searcher.search(tq, 10);
160         printTopDocs(topDocs);
161 } catch (Exception e) {
162 e.printStackTrace();
163 }
164     }
165     /**
166      * 布尔查询
167      * 搜索的条件往往是多个的,如要查询名称包含“电脑” 或 “thinkpad”的商品,就需要两个词项查询做或合并。布尔查询就是用来组合多个子查询的。
168      * 每个子查询称为布尔字句 BooleanClause,布尔字句自身也可以是组合的。 组合关系支持如下四种:
169      * Occur.SHOULD 或
170      * Occur.MUST 且
171      * Occur.MUST_NOT 且非
172      * Occur.FILTER 同 MUST,但该字句不参与评分
173      * 布尔查询默认的最大字句数为1024,在将通配符查询这样的查询rewriter为布尔查询时,往往会产生很多的字句,可能抛出TooManyClauses 异常。
174      * 可通过BooleanQuery.setMaxClauseCount(int)设置最大字句数。
175      */
176     @Test
177     public void booleanQuery() {
178      try {
179 // 创建一个indexsearcher对象
180 IndexSearcher searcher = getIndexSearcher();
181 BooleanQuery.Builder builder = new BooleanQuery.Builder();
182 // 书内容
183 QueryParser queryParser = new QueryParser("bookcontent", new IKAnalyzer());
184     Query query1 = queryParser.parse("西游记");
185     builder.add(query1, Occur.MUST);
186     // 书名称
187     Query qymc = new FuzzyQuery(new Term("bookname", "西游记"));
188 builder.add(qymc, Occur.MUST);
189 // 书类型
190 Query gmsfhm = new TermQuery(new Term("booktype", "小说"));
191 builder.add(gmsfhm, Occur.MUST);
192 BooleanQuery booleanQuery = builder.build();
193         TopDocs topDocs = searcher.search(booleanQuery, 10);
194         printTopDocs(topDocs);
195 } catch (Exception e) {
196 e.printStackTrace();
197 }
198     }
199 
200     /**
201      * 短语查询
202      * 最常用的查询,匹配特定序列的多个词项。PhraserQuery使用一个位置移动因子(slop)来决定任意两个词项的位置可最大移动多少个位置来进行匹配,默认为0。
203      * 有两种方式来构建对象:
204      * 注意:所有加入的词项都匹配才算匹配(即使是你在同一位置加入多个词项)。如果需要在同一位置匹配多个同义词中的一个,适合用MultiPhraseQuery
205      */
206     @Test
207     public void phraseQuery() {
208      try {  
209 PhraseQuery phraseQuery1 = new PhraseQuery("bookcontent", "根据", "明代");
210 PhraseQuery phraseQuery2 = new PhraseQuery(0, "bookcontent", "根据", "明代");
211 PhraseQuery phraseQuery3 = new PhraseQuery("bookcontent", "笔记本电脑", "联想");
212 PhraseQuery phraseQuery4 = new PhraseQuery.Builder()
213 
214     .add(new Term("bookcontent", "根据"), 4)
215 
216     .add(new Term("bookcontent", "施耐"), 5).build();
217 // 这两句等同
218 PhraseQuery phraseQuery5 = new PhraseQuery.Builder()
219 
220     .add(new Term("bookcontent", "笔记本电脑"), 0)
221 
222     .add(new Term("bookcontent", "联想"), 1).build();
223 
224  
225 
226 doSearch(phraseQuery2);
227 } catch (Exception e) {
228 e.printStackTrace();
229 }
230     }
231     /**
232      * 多重短语查询
233      * 短语查询的一种更通用的用法,支持同位置多个词的OR匹配。通过里面的Builder来构建MultiPhraseQuery:
234      */
235     @Test
236     public void multiPhraseQuery() {
237      try {  
238      // 4 MultiPhraseQuery 多重短语查询
239 
240      Term[] terms = new Term[2];
241 
242      terms[0] = new Term("bookcontent", "根据");
243 
244      terms[1] = new Term("bookcontent", "根据明代");
245 
246      Term t = new Term("bookcontent", "施耐");
247 
248      MultiPhraseQuery multiPhraseQuery = new MultiPhraseQuery.Builder()
249 
250          .add(terms).add(t).build();
251 
252      // 对比 PhraseQuery在同位置加入多个词 ,同位置的多个词都需匹配,所以查不出。
253 
254      PhraseQuery pquery = new PhraseQuery.Builder().add(terms[0], 0)
255 
256          .add(terms[1], 0).add(t, 1).build();
257 
258 doSearch(multiPhraseQuery);
259 
260 } catch (Exception e) {
261 
262 e.printStackTrace();
263 }
264     }
265     /**
266 
267      * 临近查询(跨度查询)
268 
269      * 用于更复杂的短语查询,可以指定词间位置的最大间隔跨度。通过组合一系列的SpanQuery 实例来进行查询,可以指定是否按顺序匹配、slop、gap
270 
271      */
272     @Test
273     public void spanNearQuery() {
274      try {  
275      // SpanNearQuery 临近查询
276      SpanTermQuery tq1 = new SpanTermQuery(new Term("bookcontent", "中央电视台"));
277      SpanTermQuery tq2 = new SpanTermQuery(new Term("bookcontent", "无锡"));
278      SpanNearQuery spanNearQuery = new SpanNearQuery(
279          new SpanQuery[] { tq1, tq2 }, 0, true);
280      // SpanNearQuery 临近查询 gap slop 使用
281      SpanNearQuery.Builder spanNearQueryBuilder = SpanNearQuery
282          .newOrderedNearQuery("bookcontent");
283      spanNearQueryBuilder.addClause(tq1).addGap(0).setSlop(1)
284          .addClause(tq2);
285      SpanNearQuery spanNearQuery5 = spanNearQueryBuilder.build();
286 //     IndexSearcher searcher = getIndexSearcher();
287 // TopDocs topDocs = searcher.search(spanNearQueryBuilder, 10);
288 doSearch(spanNearQuery);
289 } catch (Exception e) {
290 e.printStackTrace();
291 }
292     }
293 
294     /**
295      * 词项范围查询
296      * 用于查询包含某个范围内的词项的文档,如以字母开头a到c的词项。词项在反向索引中是排序的,只需指定的开始词项、结束词项,就可以查询该范围的词项。
297 
298      * 如果是做数值的范围查询则用 PointRangeQuery
299 
300      * 参数说明:
301 
302      * 第1个参数:要查询的字段-field
303 
304      * 第2个参数::下边界词-lowerTerm
305 
306      * 第3个参数:上边界词-upperTerm
307 
308      * 第4个参数:是否包含下边界-includeLower
309 
310      * 第5个参数:是否包含上边界 includeUpper
311 
312      */
313 
314     @Test
315 
316     public void termRangeQuery() {
317 
318      try {   
319 
320      // TermRangeQuery 词项范围查询
321 
322      TermRangeQuery termRangeQuery = TermRangeQuery.newStringRange("bookcontent",
323 
324          "中央电视台", "同名小说改编", false, true);
325 
326 doSearch(termRangeQuery);
327 
328 } catch (Exception e) {
329 
330 e.printStackTrace();
331 
332 }
333 
334     }
335 
336     
337 
338     /**
339 
340      * 前缀查询
341 
342      * PrefixQuery:前缀查询,查询包含以xxx为前缀的词项的文档,是通配符查询,如 app,实际是 app*
343 
344      */
345 
346     @Test
347 
348     public void prefixQuery() {
349 
350      try {   
351 
352      // PrefixQuery 前缀查询
353 
354      PrefixQuery prefixQuery = new PrefixQuery(new Term("bookcontent", "中国"));
355 
356 doSearch(prefixQuery);
357 
358 } catch (Exception e) {
359 
360 e.printStackTrace();
361 
362 }
363 
364     }
365 
366     
367 
368     /**
369 
370      * 通配符查询
371 
372      * WildcardQuery:通配符查询, *表示0个或多个字符,?表示1个字符,\是转义符。通配符查询可能会比较慢,不可以通配符开头(那样就是所有词项了)
373 
374      */
375 
376     @Test
377 
378     public void wildcardQuery() {
379 
380      try {   
381 
382      // WildcardQuery 通配符查询
383 
384      WildcardQuery wildcardQuery = new WildcardQuery(
385 
386          new Term("bookcontent", "中国*"));
387 
388 doSearch(wildcardQuery);
389 
390 } catch (Exception e) {
391 
392 e.printStackTrace();
393 
394 }
395 
396     }
397 
398     
399 
400     /**
401 
402      * 正则表达式查询
403 
404      * RegexpQuery:正则表达式查询,词项符合某正则表达式
405 
406      */
407 
408     @Test
409 
410     public void regexpQuery() {
411 
412      try {   
413 
414      // RegexpQuery 正则表达式查询
415 
416      RegexpQuery regexpQuery = new RegexpQuery(new Term("bookcontent", "厉害.{4}"));
417 
418 doSearch(regexpQuery);
419 
420 } catch (Exception e) {
421 
422 e.printStackTrace();
423 
424 }
425 
426     }
427 
428     
429 
430      
431 
432     /**
433 
434      * 模糊查询
435 
436      * 简单地与索引词项进行相近匹配,允许最大2个不同字符。常用于拼写错误的容错:如把 “thinkpad” 拼成 “thinkppd”或 “thinkd”,使用FuzzyQuery 仍可搜索到正确的结果。
437 
438      */
439 
440     @Test
441 
442     public void fuzzyQuery() {
443 
444      try {   
445 
446      // FuzzyQuery 模糊查询
447 
448      FuzzyQuery fuzzyQuery = new FuzzyQuery(new Term("bookcontent", "猪八戒"));
449 
450  
451 
452      FuzzyQuery fuzzyQuery2 = new FuzzyQuery(new Term("bookcontent", "thinkd"), 2);
453 
454  
455 
456      FuzzyQuery fuzzyQuery3 = new FuzzyQuery(new Term("bookcontent", "thinkpaddd"));
457 
458  
459 
460      FuzzyQuery fuzzyQuery4 = new FuzzyQuery(new Term("bookcontent", "thinkdaddd"));
461 
462 doSearch(fuzzyQuery);
463 
464 } catch (Exception e) {
465 
466 e.printStackTrace();
467 
468 }
469 
470     }
471 
472     
473 
474     
475 
476     /**
477 
478      * 数值查询
479 
480      * 前提:查询的数值字段必须索引。通过 IntPoint, LongPoint, FloatPoint, or DoublePoint 中的方法构建对应的查询。以IntPoint为例:
481 
482      */
483 
484     @Test
485 
486     public void pointQuery() {
487 
488      try {   
489 
490      // 精确值查询
491 
492      Query exactQuery = IntPoint.newExactQuery("bookprice", 123);
493 
494  
495 
496      // 数值范围查询
497 
498      Query pointRangeQuery = IntPoint.newRangeQuery("bookprice", 111,134);
499 
500  
501 
502      // 集合查询
503 
504      Query setQuery = IntPoint.newSetQuery("bookprice", 1999900, 1000000,2000000);
505 
506 doSearch(exactQuery);
507 
508 } catch (Exception e) {
509 
510 e.printStackTrace();
511 
512 }
513 
514     }
515 
516      
517 
518     /**
519 
520      * 查询解析生成器
521 
522      * QueryParser 查询解析生成器
523 
524      * Lucene QueryPaser包中提供了两类查询解析器:
525 
526      * A. 传统的解析器:QueryParser和MultiFieldQueryParser
527 
528      * B. 基于新的 flexible 框架的解析器:StandardQueryParser
529 
530      */
531 
532     @Test
533 
534     public void QueryParser() {
535 
536      try {   
537 
538      QueryParser parser = new QueryParser("bookcontent", new IKAnalyzer());
539 
540      //parser.setPhraseSlop(2);
541 
542      Query query = parser.parse("中国文艺央视");
543 
544 //     sortSearch(query);
545 
546      highLightSearch(query);
547 
548 } catch (Exception e) {
549 
550 e.printStackTrace();
551 
552 }
553 
554     }
555 
556     
557 
558     /**
559 
560      * 传统解析器-多默认字段
561 
562      * B. 基于新的 flexible 框架的解析器:StandardQueryParser
563 
564      */
565 
566     @Test
567 
568     public void MultiFieldQueryParser() {
569 
570      try {    
571 
572      String[] multiDefaultFields = { "bookname", "booktype", "bookcontent" };
573 
574      org.apache.lucene.queryparser.classic.MultiFieldQueryParser multiFieldQueryParser = new org.apache.lucene.queryparser.classic.MultiFieldQueryParser(
575 
576              multiDefaultFields, new IKAnalyzer());
577 
578      // 设置默认的组合操作,默认是 OR
579 
580      multiFieldQueryParser.setDefaultOperator(Operator.OR);
581 
582      Query query = multiFieldQueryParser.parse("西游记》又称央视86版《西游记》,改编自明12345678901");
583 
584 doSearch(query);
585 
586 } catch (Exception e) {
587 
588 e.printStackTrace();
589 
590 }
591 
592     }
593 
594     
595 
596     /**
597 
598      * 新解析框架的标准解析器
599 
600      * B. 基于新的 flexible 框架的解析器:StandardQueryParser
601 
602      */
603 
604     @Test
605 
606     public void StandardQueryParser() {
607 
608      try {    
609 
610      SimpleQueryParser queryParserHelper = new SimpleQueryParser(new IKAnalyzer(),"bookcontent");
611 
612      // 设置默认字段
613 
614      // queryParserHelper.setMultiFields(CharSequence[] fields);
615 
616      // queryParserHelper.setPhraseSlop(8);
617 
618      // Query query = queryParserHelper.parse("a AND b", "defaultField");
619 
620      Query query5 = queryParserHelper.parse("央视");
621 
622      sortSearch(query5);
623 
624 } catch (Exception e) {
625 
626 e.printStackTrace();
627 
628 }
629 
630     }
631 
632     
633 
634     /**
635 
636      * 高亮排序查询
637 
638      * @throws InvalidTokenOffsetsException
639 
640      */
641 
642     private void highLightSearch(Query query) throws InvalidTokenOffsetsException {
643 
644      // 获取一个indexReader对象
645 
646 try {
647 
648 Analyzer ikanalyzer = new IKAnalyzer();
649 
650 IndexSearcher searcher = getIndexSearcher();
651 
652 //true表示降序
653 
654 //SortField.Type.SCORE  根据相关度进行排序(默认)
655 
656 //SortField.Type.DOC    根据文档编号或者说是索引顺序
657 
658 //SortField.Type.FLOAT(Long等),根据fieldName的数值类型进行排序
659 
660 SortField sortField = new SortField("bookprice",SortField.Type.INT,false);
661 
662 Sort sort = new Sort(sortField);
663 
664  
665 
666 TopDocs topDocs = searcher.search(query, 10, sort);
667 
668      System.out.println("数字查询");  
669 
670         System.out.println("命中结果数为: "+ topDocs.totalHits);
671 
672         // 返回查询结果。遍历查询结果并输出。
673 
674 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
675 
676 for (ScoreDoc scoreDoc : scoreDocs) {
677 
678 int doc = scoreDoc.doc;
679 
680 Document document = searcher.doc(doc);  
681 
682 String text = document.get("bookcontent");  
683 
684         SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>");  
685 
686         Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));  
687 
688         highlighter.setTextFragmenter(new SimpleFragmenter(text.length()));  
689 
690         if (text != null) {  
691 
692             TokenStream tokenStream = ikanalyzer.tokenStream("bookcontent", new StringReader(text));  
693 
694             String highLightText = highlighter.getBestFragment(tokenStream,text);  
695 
696             System.out.println("高亮显示第 " + (doc + 1) + " 条检索结果如下所示:");  
697 
698             System.out.println("bookcontent: "+highLightText);  
699 
700         }  
701 
702  
703 
704 // 打印content字段的值
705 
706 System.out.println("bookid: "+document.get("bookid"));
707 
708 System.out.println("bookname: "+document.get("bookname"));
709 
710 System.out.println("booktype: "+document.get("booktype"));
711 
712 System.out.println("bookprice: "+document.get("bookprice"));
713 
714 System.out.println("bookdate: "+document.get("bookdate"));
715 
716 // System.out.println("bookcontent: "+document.get("bookcontent"));
717 
718 System.out.println("查询得分是: "+scoreDoc.score);
719 
720 System.out.println("--------------我是分割线------------------");
721 
722 }
723 
724 } catch (IOException e) {
725 
726 e.printStackTrace();
727 
728 }
729 
730     }
731 
732     
733 
734     /**
735 
736      * 排序查询
737 
738      */
739 
740     private void sortSearch(Query query) {
741 
742      // 获取一个indexReader对象
743 
744 try {
745 
746 IndexSearcher searcher = getIndexSearcher();
747 
748 //true表示降序
749 
750 //SortField.Type.SCORE  根据相关度进行排序(默认)
751 
752 //SortField.Type.DOC    根据文档编号或者说是索引顺序
753 
754 //SortField.Type.FLOAT(Long等),根据fieldName的数值类型进行排序
755 
756 SortField sortField = new SortField("bookcontent",SortField.Type.SCORE,false);
757 
758 Sort sort = new Sort(sortField);
759 
760  
761 
762 TopDocs topDocs = searcher.search(query, 10, sort);
763 
764      System.out.println("数字查询");  
765 
766         System.out.println("命中结果数为: "+ topDocs.totalHits);
767 
768         // 返回查询结果。遍历查询结果并输出。
769 
770 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
771 
772 for (ScoreDoc scoreDoc : scoreDocs) {
773 
774 int doc = scoreDoc.doc;
775 
776 Document document = searcher.doc(doc);  
777 
778 // 打印content字段的值
779 
780 System.out.println("bookid: "+document.get("bookid"));
781 
782 System.out.println("bookname: "+document.get("bookname"));
783 
784 System.out.println("booktype: "+document.get("booktype"));
785 
786 System.out.println("bookprice: "+document.get("bookprice"));
787 
788 System.out.println("bookcontent: "+document.get("bookcontent"));
789 
790 System.out.println("查询得分是: "+scoreDoc.score);
791 
792 System.out.println("--------------我是分割线------------------");
793 
794 }
795 
796 } catch (IOException e) {
797 
798 e.printStackTrace();
799 
800 }
801 
802     }
803 
804     
805 
806     /**
807 
808      * 查询打印结果
809 
810      */
811 
812     private void doSearch(Query query) {
813 
814      // 获取一个indexReader对象
815 
816 try {
817 
818 IndexSearcher searcher = getIndexSearcher();
819 
820 TopDocs topDocs = searcher.search(query, 10);
821 
822      System.out.println("数字查询");  
823 
824         System.out.println("命中结果数为: "+ topDocs.totalHits);
825 
826         // 返回查询结果。遍历查询结果并输出。
827 
828 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
829 
830 for (ScoreDoc scoreDoc : scoreDocs) {
831 
832 int doc = scoreDoc.doc;
833 
834 Document document = searcher.doc(doc);  
835 
836 // 打印content字段的值
837 
838 System.out.println("bookid: "+document.get("bookid"));
839 
840 System.out.println("bookname: "+document.get("bookname"));
841 
842 System.out.println("booktype: "+document.get("booktype"));
843 
844 System.out.println("bookcontent: "+document.get("bookcontent"));
845 
846 System.out.println("查询得分是: "+scoreDoc.score);
847 
848 System.out.println("--------------我是分割线------------------");
849 
850 }
851 
852 } catch (IOException e) {
853 
854 e.printStackTrace();
855 
856 }
857 
858     }
859 
860     
861 
862     /**
863 
864      * 打印查询结果
865 
866      */
867 
868     private void printTopDocs(TopDocs topDocs) {
869 
870      // 获取一个indexReader对象
871 
872 try {
873 
874 IndexSearcher searcher = getIndexSearcher();
875 
876      System.out.println("数字查询");  
877 
878         System.out.println("命中结果数为: "+ topDocs.totalHits);
879 
880         // 返回查询结果。遍历查询结果并输出。
881 
882 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
883 
884 for (ScoreDoc scoreDoc : scoreDocs) {
885 
886 int doc = scoreDoc.doc;
887 
888 Document document = searcher.doc(doc);  
889 
890 // 打印content字段的值
891 
892 System.out.println("bookid: "+document.get("bookid"));
893 
894 System.out.println("bookname: "+document.get("bookname"));
895 
896 System.out.println("booktype: "+document.get("booktype"));
897 
898 System.out.println("bookcontent: "+document.get("bookcontent"));
899 
900 }
901 
902 } catch (IOException e) {
903 
904 e.printStackTrace();
905 
906 }
907 
908     }
909 
910  
911 
912 }

1.1.17. MatchAllDocsQuery

 1 /**
 2 
 3      * 查询所有文档
 4 
 5      * @throws ParseException
 6 
 7      * @throws IOException
 8 
 9      */
10 
11     @Test
12 
13     public void testMatchAllDocsQuery() throws ParseException, IOException {  
14 
15         Query query = new MatchAllDocsQuery();
16 
17         IndexSearcher searcher = getIndexSearcher();
18 
19         TopDocs topDocs = searcher.search(query, 10);
20 
21         
22 
23         // 返回查询结果。遍历查询结果并输出。
24 
25 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
26 
27 for (ScoreDoc scoreDoc : scoreDocs) {
28 
29 int doc = scoreDoc.doc;
30 
31 Document document = searcher.doc(doc);  
32 
33 // 打印content字段的值
34 
35 System.out.println("bookid: "+document.get("bookid"));
36 
37 System.out.println("bookname: "+document.get("bookname"));
38 
39 System.out.println("booktype: "+document.get("booktype"));
40 
41 System.out.println("bookcontent: "+document.get("bookcontent"));
42 
43 }   
44 
45 }

1.1.18. MatchNoDocsQuery

 1 /**
 2 
 3      * 不匹配任何文档(好像没什么用)
 4 
 5      * @throws ParseException
 6 
 7      * @throws IOException
 8 
 9      */
10 
11     @Test
12 
13     public void testMatchNoDocsQuery() throws ParseException, IOException {  
14 
15         Query query = new MatchNoDocsQuery();
16 
17         IndexSearcher searcher = getIndexSearcher();
18 
19         TopDocs topDocs = searcher.search(query, 10);
20 
21         
22 
23         // 返回查询结果。遍历查询结果并输出。
24 
25 ScoreDoc[] scoreDocs = topDocs.scoreDocs;
26 
27 for (ScoreDoc scoreDoc : scoreDocs) {
28 
29 int doc = scoreDoc.doc;
30 
31 Document document = searcher.doc(doc);  
32 
33 // 打印content字段的值
34 
35 System.out.println("bookid: "+document.get("bookid"));
36 
37 System.out.println("bookname: "+document.get("bookname"));
38 
39 System.out.println("booktype: "+document.get("booktype"));
40 
41 System.out.println("bookcontent: "+document.get("bookcontent"));
42 
43 }   
44 
45     }

猜你喜欢

转载自www.cnblogs.com/bestlmc/p/11865725.html