Java tutorial
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package cn.hbu.cs.esearch.service.impl; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexableField; import org.apache.lucene.index.MultiReader; import org.apache.lucene.queryparser.classic.QueryParser; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.MatchAllDocsQuery; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.QueryScorer; import org.apache.lucene.search.highlight.Scorer; import org.apache.lucene.search.highlight.SimpleHTMLFormatter; import org.apache.lucene.util.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.base.Strings; import cn.hbu.cs.esearch.core.EsearchException; import cn.hbu.cs.esearch.core.EsearchMultiReader; import cn.hbu.cs.esearch.core.EsearchSystem; import cn.hbu.cs.esearch.model.SearchHit; import cn.hbu.cs.esearch.model.SearchRequest; import cn.hbu.cs.esearch.model.SearchResult; import cn.hbu.cs.esearch.service.SearchService; /** * @author Li Ming */ public class EsearchSearchServiceImpl<R extends IndexReader> implements SearchService { private static final Logger LOGGER = LoggerFactory.getLogger(EsearchSearchServiceImpl.class); private EsearchSystem esearchSystem; public EsearchSearchServiceImpl(EsearchSystem esearchSystem) { this.esearchSystem = esearchSystem; } private static Map<String, String[]> convert(Document document, SearchRequest.SearchType searchType) { Map<String, String[]> map = new HashMap<String, String[]>(); if (document != null) { List<IndexableField> fields = document.getFields(); Iterator<IndexableField> iter = fields.iterator(); while (iter.hasNext()) { IndexableField fld = iter.next(); String fieldname = fld.name(); if (searchType == SearchRequest.SearchType.SIMPLE_QUERY) { if (fieldname.equals("_path") || fieldname.equals("_name")) { map.put(fieldname, document.getValues(fieldname)); } } else if (searchType == SearchRequest.SearchType.QUERY_AND_FETCH) { map.put(fieldname, document.getValues(fieldname)); } } } return map; } @Override public SearchResult search(SearchRequest sResquest) throws EsearchException { try { esearchSystem.flushEvents(2000); } catch (EsearchException e) { LOGGER.error("Esearch flush events error. \n{}", e); } String queryString = sResquest.getQuery(); String queryField = sResquest.getField(); LOGGER.info("The search request coming: queryField:{},queryString:{}", queryField, queryString); Analyzer analyzer = esearchSystem.getAnalyzer(); QueryParser queryParser = new QueryParser(Version.LUCENE_43, queryField, analyzer); SearchResult result = new SearchResult(); List<EsearchMultiReader<R>> readers = null; MultiReader multiReader = null; IndexSearcher searcher = null; try { Query query = null; if (Strings.isNullOrEmpty(queryString)) { query = new MatchAllDocsQuery(); } else { query = queryParser.parse(queryString); } readers = esearchSystem.getIndexReaders(); multiReader = new MultiReader(readers.toArray(new IndexReader[readers.size()]), false); searcher = new IndexSearcher(multiReader); long start = System.currentTimeMillis(); TopDocs docs = searcher.search(query, null, sResquest.getSize()); long end = System.currentTimeMillis(); result.setTime(end - start); result.setTotalDocs(multiReader.numDocs()); result.setTotalHits(docs.totalHits); LOGGER.info("Got {} hits. Cost:{} ms", docs.totalHits, end - start); if (sResquest.getSearchType() == SearchRequest.SearchType.COUNT) { return result; } ScoreDoc[] scoreDocs = docs.scoreDocs; ArrayList<SearchHit> hitList = new ArrayList<SearchHit>(scoreDocs.length); for (ScoreDoc scoreDoc : scoreDocs) { SearchHit hit = new SearchHit(); hit.setScore(scoreDoc.score); int docID = scoreDoc.doc; Document doc = multiReader.document(docID); String content = doc.get(queryField); Scorer qs = new QueryScorer(query); SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span class=\"hl\">", "</span>"); Highlighter hl = new Highlighter(formatter, qs); String[] fragments = hl.getBestFragments(analyzer, queryField, content, 1); Map<String, String[]> fields = convert(doc, sResquest.getSearchType()); fields.put("fragment", fragments); hit.setFields(fields); hitList.add(hit); } result.setHits(hitList.toArray(new SearchHit[hitList.size()])); return result; } catch (Exception e) { LOGGER.error(e.getMessage(), e); throw new EsearchException(e.getMessage(), e); } finally { if (multiReader != null) { try { multiReader.close(); } catch (IOException e) { LOGGER.error(e.getMessage(), e); } } esearchSystem.returnIndexReaders(readers); } } }