package com.jspxcms.common.fulltext; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.SearcherManager; import org.apache.lucene.search.TopDocs; import org.springframework.beans.factory.InitializingBean; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; import com.jspxcms.common.orm.Limitable; import com.jspxcms.common.orm.QuerydslUtils; import com.mysema.query.lucene.LuceneQuery; import com.mysema.query.types.EntityPath; import com.mysema.query.types.Predicate; /** * 默认全文检索模板 * * 每次查询前执行SearcherManager.maybeRefresh(); * * @author liufang * */ public class DefaultLuceneIndexTemplate implements LuceneIndexTemplate, InitializingBean { private boolean isAutoCommit = false; private IndexWriter indexWriter; private SearcherManager searcherManager; public DefaultLuceneIndexTemplate() { } public DefaultLuceneIndexTemplate(IndexWriter indexWriter, SearcherManager searcherManager) { this.indexWriter = indexWriter; this.searcherManager = searcherManager; } public List<String> list(Query query, String field, Limitable limitable) { try { IndexSearcher searcher = null; try { searcherManager.maybeRefresh(); searcher = searcherManager.acquire(); int n = limitable.getLastResult(); n = n <= 0 ? 2000 : n; TopDocs results = searcher.search(query, n); int length = results.scoreDocs.length; List<String> list = new ArrayList<String>(length); for (ScoreDoc hit : results.scoreDocs) { list.add(searcher.doc(hit.doc).get(field)); } return list; } finally { if (searcher != null) { searcherManager.release(searcher); } } } catch (Exception e) { throw new LuceneException("Error during searching.", e); } } public Page<String> page(Query query, String field, Pageable pageable) { try { IndexSearcher searcher = null; try { searcherManager.maybeRefresh(); searcher = searcherManager.acquire(); int n = pageable.getOffset() + pageable.getPageSize(); TopDocs results = searcher.search(query, n); int length = results.scoreDocs.length; int size = length - pageable.getOffset(); List<String> content; if (size > 0) { content = new ArrayList<String>(size); ScoreDoc hit; for (int i = pageable.getOffset(); i < length; i++) { hit = results.scoreDocs[i]; content.add(searcher.doc(hit.doc).get(field)); } } else { content = Collections.emptyList(); } int total = results.totalHits; return new PageImpl<String>(content, pageable, total); } finally { if (searcher != null) { searcherManager.release(searcher); } } } catch (Exception e) { throw new LuceneException("Error during searching.", e); } } public List<Document> list(Predicate predicate, EntityPath<Document> entityPath, Limitable limitable) { try { IndexSearcher searcher = null; try { searcherManager.maybeRefresh(); searcher = searcherManager.acquire(); LuceneQuery query = new LuceneQuery(searcher); query.where(predicate); QuerydslUtils.applySorting(query, entityPath, limitable.getSort()); Integer firstResult = limitable.getFirstResult(); if (firstResult != null && firstResult > 0) { query.offset(firstResult); } Integer maxResults = limitable.getMaxResults(); if (maxResults != null && maxResults > 0) { query.limit(maxResults); } return query.list(); } finally { if (searcher != null) { searcherManager.release(searcher); } } } catch (Exception e) { throw new LuceneException("Error during searching.", e); } } public Page<Document> page(Predicate predicate, EntityPath<Document> entityPath, Pageable pageable) { try { IndexSearcher searcher = null; try { searcherManager.maybeRefresh(); searcher = searcherManager.acquire(); LuceneQuery query = new LuceneQuery(searcher); long total = query.count(); List<Document> content; if (total > pageable.getOffset()) { query.offset(pageable.getOffset()); query.limit(pageable.getPageSize()); QuerydslUtils.applySorting(query, entityPath, pageable.getSort()); content = query.list(); } else { content = Collections.emptyList(); } Page<Document> page = new PageImpl<Document>(content, pageable, total); return page; } finally { if (searcher != null) { searcherManager.release(searcher); } } } catch (Exception e) { throw new LuceneException("Error during searching.", e); } } public void addDocument(Document document) { try { indexWriter.addDocument(document); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during adding a document.", e); } } public void addDocuments(Collection<Document> documents) { try { indexWriter.addDocuments(documents); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during adding a document.", e); } } public void updateDocument(Term term, Document document) { try { indexWriter.updateDocument(term, document); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during updating a document.", e); } } public void deleteDocuments(Term... terms) { try { indexWriter.deleteDocuments(terms); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during deleting a document.", e); } } public void deleteDocuments(Term term) { try { indexWriter.deleteDocuments(term); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during deleting a document.", e); } } public void deleteDocuments(Query... queries) { try { indexWriter.deleteDocuments(queries); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during deleting a document.", e); } } public void deleteDocuments(Query query) { try { indexWriter.deleteDocuments(query); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during deleting a document.", e); } } public void deleteAll() { try { indexWriter.deleteAll(); if (isAutoCommit) { indexWriter.commit(); } } catch (Exception e) { throw new LuceneException("Error during deleting a document.", e); } } public void afterPropertiesSet() throws Exception { if (indexWriter == null) { throw new IllegalArgumentException("indexFactory is required"); } if (searcherManager == null) { throw new IllegalArgumentException("indexFactory is required"); } } public void setIndexWriter(IndexWriter indexWriter) { this.indexWriter = indexWriter; } public void setSearcherManager(SearcherManager searcherManager) { this.searcherManager = searcherManager; } public void setAutoCommit(boolean isAutoCommit) { this.isAutoCommit = isAutoCommit; } }