zoukankan      html  css  js  c++  java
  • Lucene8学习: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] 
    " +
     77 
     78           "该剧讲述的是孙悟空、猪八戒、沙僧辅保大唐高僧玄奘去西天取经,师徒四人一路抢滩涉险,降妖伏怪,历经八十一难,取回真经,终修正果的故事。
    " +
     79 
     80           "《西游记》于1982年7月3日开机,同年10月1日首播试集《除妖乌鸡国》。1986年春节在央视首播前11集,1988年25集播出。
    " +
     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集
    " +
    102            "《水浒传》是由中央电视台与中国电视剧制作中心联合出品的43集电视连续剧,根据明代施耐庵的同名小说改编。 [1]  由张绍林执导,杨争光 、冉平改编,李雪健、周野芒、臧金生、丁海峰、赵小锐领衔主演。
    " +
    103 
    104            "该剧讲述的是宋朝徽宗时皇帝昏庸、奸臣当道、官府腐败、贪官污吏陷害忠良,弄得民不聊生,许多正直善良的人被官府逼得无路可走,被迫奋起反抗,最终108条好汉聚义梁山泊,但随后宋江对朝廷的投降使得一场轰轰烈烈的农民起义最后走向失败的故事。 [2] 
    " +
    105            "《水浒传》于1998年1月8日在中央电视台一套首播。 [3] 
    " +
    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     }
  • 相关阅读:
    Java学习笔记之---单例模型
    Java学习笔记之---内部类
    Java项目案例之--封装的实例
    Java学习笔记之---构造方法
    Java学习笔记之---static
    Java学习笔记之---面向对象
    咨询顾问与逻辑思客
    最重要与靠不住之间如何平衡
    《网络借贷信息中介机构业务活动管理暂行办法》
    商业银行法律法规与监管要求汇总
  • 原文地址:https://www.cnblogs.com/bestlmc/p/11865725.html
Copyright © 2011-2022 走看看