/* * Copyright (c) www.bugull.com * * Licensed 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 net.tooan.ynpay.third.mongodb.lucene; import net.tooan.ynpay.third.jfinal.log.Logger; import net.tooan.ynpay.third.mongodb.cache.DaoCache; import net.tooan.ynpay.third.mongodb.cache.FieldsCache; import net.tooan.ynpay.third.mongodb.cache.IndexSearcherCache; import net.tooan.ynpay.third.mongodb.exception.FieldException; import net.tooan.ynpay.third.mongodb.mapper.FieldUtil; import net.tooan.ynpay.third.mongodb.mapper.InternalDao; import net.tooan.ynpay.third.mongodb.mapper.MapperUtil; import net.tooan.ynpay.third.mongodb.mapper.StringUtil; import org.apache.commons.lang.StringUtils; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.search.*; import java.io.IOException; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; /** * @author Frank Wen(xbwen@hotmail.com) */ public class BuguSearcher<T> { private final static Logger logger = Logger.getLogger(BuguSearcher.class); private Class<T> clazz; private IndexSearcher searcher; private IndexReader reader; private InternalDao<T> dao; private Query query; private Sort sort; private Filter filter; private int pageNumber = 1; private int pageSize = 20; private int maxPage = 100; private int resultCount; private BuguHighlighter highlighter; public BuguSearcher(Class<T> clazz) { this.clazz = clazz; String name[] = MapperUtil.getEntityName(clazz); searcher = IndexSearcherCache.getInstance().get(StringUtils.join(name, ".")); reader = searcher.getIndexReader(); reader.incRef(); } public BuguSearcher<T> setQuery(Query query) { this.query = query; return this; } public BuguSearcher<T> setSort(Sort sort) { this.sort = sort; return this; } public BuguSearcher<T> setFilter(Filter filter) { this.filter = filter; return this; } public BuguSearcher<T> setMaxPage(int maxPage) { this.maxPage = maxPage; return this; } public BuguSearcher<T> setPageNumber(int pageNumber) { this.pageNumber = pageNumber; return this; } public BuguSearcher<T> setPageSize(int pageSize) { this.pageSize = pageSize; return this; } public BuguSearcher<T> setHighlighter(BuguHighlighter highlighter) { this.highlighter = highlighter; return this; } public int getResultCount() { return resultCount; } public List<T> search(Query query) { this.query = query; return search(); } public List<T> search(Query query, Sort sort) { this.query = query; this.sort = sort; return search(); } public List<T> search(Query query, Filter filter) { this.query = query; this.filter = filter; return search(); } public List<T> search(Query query, Filter filter, Sort sort) { this.query = query; this.filter = filter; this.sort = sort; return search(); } public List<T> search() { TopDocs topDocs = null; try { if (sort == null) { topDocs = searcher.search(query, filter, maxPage * pageSize); } else { topDocs = searcher.search(query, filter, maxPage * pageSize, sort); } } catch (IOException ex) { logger.error("Something is wrong when doing lucene search", ex); } if (topDocs == null) { return Collections.emptyList(); } resultCount = topDocs.totalHits; ScoreDoc[] docs = topDocs.scoreDocs; List<T> list = new ArrayList<T>(); dao = DaoCache.getInstance().get(clazz); int begin = (pageNumber - 1) * pageSize; int end = begin + pageSize; if (end > resultCount) { end = resultCount; } //fix lazy or not boolean lazy = needLazy(); //get from db for (int i = begin; i < end; i++) { Document doc = null; try { doc = searcher.doc(docs[i].doc); } catch (IOException ex) { logger.error("Lucene IndexSearcher can not get the document", ex); } if (doc != null) { String id = doc.get(FieldsCache.getInstance().getIdFieldName(clazz)); T t = lazy ? dao.findOneLazily(id) : dao.findOne(id); if (t != null) { list.add(t); } } } //process highlighter if (highlighter != null) { for (Object obj : list) { highlightObject(obj); } } return list; } private boolean needLazy() { if (highlighter == null) { return true; } boolean lazy = true; String[] fields = highlighter.getFields(); Set<String> keys = dao.getKeys().keySet(); for (String f : fields) { if (!keys.contains(f)) { lazy = false; break; } } return lazy; } private void highlightObject(Object obj) { String[] fields = highlighter.getFields(); for (String fieldName : fields) { if (!fieldName.contains(".")) { Field field = null; try { field = FieldsCache.getInstance().getField(clazz, fieldName); } catch (FieldException ex) { logger.error(ex.getMessage(), ex); } Object fieldValue = FieldUtil.get(obj, field); if (fieldValue != null) { String result = null; try { result = highlighter.getResult(fieldName, fieldValue.toString()); } catch (Exception ex) { logger.error("Something is wrong when getting the highlighter result", ex); } if (!StringUtil.isEmpty(result)) { FieldUtil.set(obj, field, result); } } } } } public void close() { try { reader.decRef(); } catch (IOException ex) { logger.error("Something is wrong when decrease the reference of IndexReader", ex); } } public IndexSearcher getSearcher() { return searcher; } }