1.1.三种方案
// 在这四个域中检索 String[] fields = { "phoneType", "name", "category", "price" }; Query query = new MultiFieldQueryParser(Version.LUCENE_36, fields, analyzer).parse(keyword);第三种方法就是使用高级DisjunctionMaxQuery类,它会封装一个或者多个任意的查询,将匹配的文档进行OR操作。
1.2.方案选择
2.1.两种方案
2.2.QueryFilter方案
import org.apache.lucene.search.CachingWrapperFilter; import org.apache.lucene.search.Query; import org.apache.lucene.search.QueryWrapperFilter; public class QueryFilter extends CachingWrapperFilter { /** * Constructs a filter which only matches documents matching * <code>query</code>. */ public QueryFilter(Query query) { super(new QueryWrapperFilter(query)); } public boolean equals(Object o) { return super.equals((QueryFilter) o); } public int hashCode() { return super.hashCode() ^ 0x923F64B9; } }
//简单实现对keyword的搜索 public static void search(String keyword) throws IOException, ParseException { QueryParser queryParser = new QueryParser("content",new SimpleAnalyzer()); Query query = queryParser.parse(keyword.trim()); QueryFilter filter = new QueryFilter(query); //检索 search(query, filter); } //在搜索oldKeyword的结果集中搜索newKeyword public static void searchInResult(String newKeyword, String oldKeyword) throws ParseException, IOException { QueryParser queryParser = new QueryParser("content",new SimpleAnalyzer()); Query query = queryParser.parse(newKeyword.trim()); Query oldQuery = queryParser.parse(oldKeyword.trim()); QueryFilter oldFilter = new QueryFilter(oldQuery); CachingWrapperFilter filter = new CachingWrapperFilter(oldFilter); //检索 search(query, filter); } private static void search(Query query, Filter filter) throws IOException, ParseException { IndexSearcher ins = new IndexSearcher("d:/tesindex"); Hits hits = ins.search(query, filter); for (int i = 0; i < hits.length(); i++) { Document doc = hits.doc(i); System.out.println(doc.get("content")); } }
2.3.BooleanQuery方案
//创建BooleanQuery BooleanQuery booleanQuery = new BooleanQuery(); //多域检索,在这四个域中检索 String[] fields = { "phoneType", "name", "category","free" }; Query multiFieldQuery = new MultiFieldQueryParser(Version.LUCENE_36, fields, analyzer).parse(keyword); //将multiFieldQuery添加到BooleanQuery中 booleanQuery.add(multiFieldQuery, BooleanClause.Occur.MUST); //如果osKeyword不为空 if(osKeyword != null && !osKeyword.equals("") && !osKeyword.equals("null")){ TermQuery osQuery = new TermQuery(new Term("phoneType",osKeyword)); //将osQuery添加到BooleanQuery中 booleanQuery.add(osQuery, BooleanClause.Occur.MUST); }
3.检索结果分页
3.1.两种方案
3.2.分页实现
/** * 对搜索返回的前n条结果进行分页显示 * @param keyWord 查询关键词 * @param pageSize 每页显示记录数 * @param currentPage 当前页 */ public void paginationQuery(String keyWord,int pageSize,int currentPage) throws ParseException, CorruptIndexException, IOException { String[] fields = {"title","content"}; QueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_36,fields,analyzer); Query query = queryParser.parse(keyWord); IndexReader indexReader = IndexReader.open(directory); IndexSearcher indexSearcher = new IndexSearcher(indexReader); //TopDocs 搜索返回的结果 TopDocs topDocs = indexSearcher.search(query, 100);//只返回前100条记录 int totalCount = topDocs.totalHits; // 搜索结果总数量 ScoreDoc[] scoreDocs = topDocs.scoreDocs; // 搜索返回的结果集合 //查询起始记录位置 int begin = pageSize * (currentPage - 1) ; //查询终止记录位置 int end = Math.min(begin + pageSize, scoreDocs.length); //进行分页查询 for(int i=begin;i<end;i++) { int docID = scoreDocs[i].doc; Document doc = indexSearcher.doc(docID); int id = NumericUtils.prefixCodedToInt(doc.get("id")); String title = doc.get("title"); System.out.println("id is : "+id); System.out.println("title is : "+title); } }
4.高亮检索结果
public void search(String fieldName, String keyword)throws CorruptIndexException, IOException, ParseException { searcher = new IndexSearcher(indexPath); QueryParser queryParse = new QueryParser(fieldName, analyzer); // 构造QueryParser,解析用户输入的检索关键字 Query query = queryParse.parse(keyword); Hits hits = searcher.search(query); for (int i = 0; i < hits.length(); i++) { Document doc = hits.doc(i); String text = doc.get(fieldName); SimpleHTMLFormatter simpleHTMLFormatter = new SimpleHTMLFormatter("<font color='red'>", "</font>"); Highlighter highlighter = new Highlighter(simpleHTMLFormatter, new QueryScorer(query)); highlighter.setTextFragmenter(new SimpleFragmenter(text.length())); if (text != null) { TokenStream tokenStream = analyzer.tokenStream(fieldName,new StringReader(text)); String highLightText = highlighter.getBestFragment(tokenStream,text); System.out.println("高亮显示第 " + (i + 1) + " 条检索结果如下所示:"); System.out.println(highLightText); } } searcher.close(); }上文的一行判断语句很重要:if(text != null),如果text为空,那么显示结果不但没有被高亮,而且得到的原始结果也会被过滤。可以再代码中加上,如果text==null,则让将原始检索结果赋给text,从而将结果显示出来。
//评分 Explanation explanation = indexSearcher.explain(query, docID); System.out.println(explanation.toString());在后台打印出来的信息如下:
2.4342022 = (MATCH) weight(name:books in 71491), product of: 0.2964393 = queryWeight(name:books), product of: 8.21147 = idf(docFreq=109, maxDocs=149037) 0.036100637 = queryNorm