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     }
01-12 11:19