package proj.zoie.example.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.log4j.Logger;
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 proj.zoie.api.IndexReaderFactory;
import proj.zoie.api.ZoieException;
import proj.zoie.api.ZoieMultiReader;
import proj.zoie.service.api.SearchHit;
import proj.zoie.service.api.SearchRequest;
import proj.zoie.service.api.SearchResult;
import proj.zoie.service.api.ZoieSearchService;
public class ExampleZoieSearchServiceImpl<R extends IndexReader> implements ZoieSearchService {
private static final Logger log = Logger.getLogger(ExampleZoieSearchServiceImpl.class);
private final IndexReaderFactory<R> _idxReaderFactory;
public ExampleZoieSearchServiceImpl(IndexReaderFactory<R> idxReaderFactory) {
_idxReaderFactory = idxReaderFactory;
}
private static Map<String, String[]> convert(Document doc) {
Map<String, String[]> map = new HashMap<String, String[]>();
if (doc != null) {
List<IndexableField> fields = doc.getFields();
Iterator<IndexableField> iter = fields.iterator();
while (iter.hasNext()) {
IndexableField fld = iter.next();
String fieldname = fld.name();
map.put(fieldname, doc.getValues(fieldname));
}
}
return map;
}
@Override
public SearchResult search(SearchRequest req) throws ZoieException {
String queryString = req.getQuery();
Analyzer analyzer = _idxReaderFactory.getAnalyzer();
QueryParser qparser = new QueryParser(Version.LUCENE_43, "content", analyzer);
SearchResult result = new SearchResult();
List<ZoieMultiReader<R>> readers = null;
MultiReader multiReader = null;
IndexSearcher searcher = null;
try {
Query q = null;
if (queryString == null || queryString.length() == 0) {
q = new MatchAllDocsQuery();
} else {
q = qparser.parse(queryString);
}
readers = _idxReaderFactory.getIndexReaders();
multiReader = new MultiReader(readers.toArray(new IndexReader[readers.size()]), false);
searcher = new IndexSearcher(multiReader);
long start = System.currentTimeMillis();
TopDocs docs = searcher.search(q, null, 10);
long end = System.currentTimeMillis();
result.setTime(end - start);
result.setTotalDocs(multiReader.numDocs());
result.setTotalHits(docs.totalHits);
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("content");
Scorer qs = new QueryScorer(q);
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span class=\"hl\">", "</span>");
Highlighter hl = new Highlighter(formatter, qs);
String[] fragments = hl.getBestFragments(analyzer, "content", content, 1);
Map<String, String[]> fields = convert(doc);
fields.put("fragment", fragments);
hit.setFields(fields);
hitList.add(hit);
}
result.setHits(hitList.toArray(new SearchHit[hitList.size()]));
return result;
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new ZoieException(e.getMessage(), e);
} finally {
if (multiReader != null) {
try {
multiReader.close();
} catch (IOException e) {
log.error(e.getMessage(), e);
}
}
_idxReaderFactory.returnIndexReaders(readers);
}
}
}