Lucene学习:lucene查询

1.1. Lucene查询

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

1.1.1. Query

封装某种查询类型的具体子类,配置查询的查询条件。Query实例将被传递给IndexSearcher的search方法。下面是常用的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     }

原文地址:https://www.cnblogs.com/bestlmc/p/11865725.html

时间: 2024-11-07 03:44:33

Lucene学习:lucene查询的相关文章

一步一步跟我学习lucene(19)---lucene增量更新和NRT(near-real-time)Query近实时查询

这两天加班,不能兼顾博客的更新,请大家见谅. 有时候我们创建完索引之后,数据源可能有更新的内容,而我们又想像数据库那样能直接体现在查询中,这里就是我们所说的增量索引.对于这样的需求我们怎么来实现呢?lucene内部是没有提供这种增量索引的实现的: 这里我们一般可能会想到,将之前的索引全部删除,然后进行索引的重建.对于这种做法,如果数据源的条数不是特别大的情况下倒还可以,如果数据源的条数特别大的话,势必会造成查询数据耗时,同时索引的构建也是比较耗时的,几相叠加,势必可能造成查询的时候数据缺失的情况

一步一步跟我学习lucene(9)---lucene搜索之拼写检查和相似度查询提示(spellcheck)

suggest应用场景 用户的输入行为是不确定的,而我们在写程序的时候总是想让用户按照指定的内容或指定格式的内容进行搜索,这里就要进行人工干预用户输入的搜索条件了:我们在用百度谷歌等搜索引擎的时候经常会看到按键放下的时候直接会提示用户是否想搜索某些相关的内容,恰好lucene在开发的时候想到了这一点,lucene提供的suggest包正是用来解决上述问题的. suggest包联想词相关介绍 suggest包提供了lucene的自动补全或者拼写检查的支持: 拼写检查相关的类在org.apache.

一步一步跟我学习lucene(16)---lucene搜索之facet查询查询示例(2)

本篇是接一步一步跟我学习lucene(14)---lucene搜索之facet索引原理和facet查询实例(http://blog.csdn.net/wuyinggui10000/article/details/45973769),上篇主要是统计facet的dim和每个种类对应的数量,个人感觉这个跟lucene的group不同的在于facet的存储类似于hash(key-field-value)形式的,而group则是单一的map(key-value)形式的,虽然都可以统计某一品类的数量,显然f

一步一步跟我学习lucene(14)---lucene搜索之facet查询原理和facet查询实例

Facet说明 我们在浏览网站的时候,经常会遇到按某一类条件查询的情况,这种情况尤以电商网站最多,以天猫商城为例,我们选择某一个品牌,系统会将该品牌对应的商品展示出来,效果图如下: 如上图,我们关注的是品牌,选购热点等方面,对于类似的功能我们用lucene的term查询当然可以,但是在数据量特别大的情况下还用普通查询来实现显然会因为FSDirectory.open等耗时的操作造成查询效率的低下,同时普通查询是全部document都扫描一遍,这样显然造成了查询效率低: lucene提供了facet

一步一步跟我学习lucene(12)---lucene搜索之分组处理group查询

grouping介绍 我们在做lucene搜索的时候,可能会用到对某个条件的数据进行统计,比如统计有多少个省份,在sql查询中我们可以用distinct来完成类似的功能,也可以用group by来对查询的列进行分组查询.在lucene中我们实现类似的功能怎么做呢,比较费时的做法时我们查询出所有的结果,然后对结果里边的省份对应的field查询出来,往set里边放,显然这种做法效率低,不可取:lucene为了解决上述问题,提供了用于分组操作的模块group,group主要用户处理不同lucene中含

一步一步跟我学习lucene(18)---lucene索引时join和查询时join使用示例

了解sql的朋友都知道,我们在查询的时候可以采用join查询,即对有一定关联关系的对象进行联合查询来对多维的数据进行整理.这个联合查询的方式挺方便的,跟我们现实生活中的托人找关系类似,我们想要完成一件事,先找自己的熟人,然后通过熟人在一次找到其他,最终通过这种手段找到想要联系到的人.有点类似于"世间万物皆有联系"的感觉. lucene的join包提供了索引时join和查询时join的功能: Index-time join 大意是索引时join提供了查询时join的支持,且IndexWr

一步一步跟我学习lucene(15)---lucene搜索之正则表达式查询RegExQuery和手机邮箱查询示例

今天快下班的时候收到了一个群友的问题,大意是读取文本文件中的内容,找出文件中的手机号和邮箱,我自己写了一个读取文档的内容的正则查询示例,用于匹配文件中是否含有邮箱或者手机号,这个等于是对之前的文本处理工具的一个梳理,同时结合lucene内部提供的正则匹配查询RegexQuery: 废话不多说了,直接上代码,这里先对文件内容读取分类处理,分为pdf word excel 和普通文本四类,不同的种类读取文本内容不一样 pdf利用pdfbox读取内容,word和excel利用poi进行读取内容,文本文

一步一步跟我学习lucene(13)---lucene搜索之自定义排序的实现原理和编写自己的自定义排序工具

自定义排序说明 我们在做lucene搜索的时候,可能会需要排序功能,虽然lucene内置了多种类型的排序,但是如果在需要先进行某些值的运算然后在排序的时候就有点显得无能为力了: 要做自定义查询,我们就要研究lucene已经实现的排序功能,lucene的所有排序都是要继承FieldComparator,然后重写内部实现,这里以IntComparator为例子来查看其实现: IntComparator相关实现 其类的声明为 public static class IntComparator exte

Lucene学习笔记

师兄推荐我学习Lucene这门技术,用了两天时间,大概整理了一下相关知识点. 一.什么是Lucene Lucene即全文检索.全文检索是计算机程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置.当用户查询时根据建立的索引查找,类似于通过字典的检索字表查字的过程. 二.Lucece全文检索和数据库检索的区别 三.Lucene的原理 (1)索引库操作原理 注意:这里面有两个关键的对象:分别是IndexWriter和IndexSearcher. 执行增删改操作用的是