@Override public AddResponse add(Collection<InputDocument> inputDocuments) { try { if (logger.isDebugEnabled()) { logger.debug("adding documents..."); } for (InputDocument inputDocument : inputDocuments) { assertIdExist(inputDocument); } for (Document document : DocumentTransformUtil.toLuceneDocuments(inputDocuments, schema)) { indexWriter.updateDocument( new Term(schema.getIdName(), document.getFieldable(schema.getIdName()).stringValue()), document, schema.getAnalyzer()); } updateCount.addAndGet(inputDocuments.size()); if (logger.isDebugEnabled()) { logger.debug("add documents finish."); } } catch (Exception e) { logger.error("add documents error", e); return new AddResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new AddResponse(); }
@Override public DeleteResponse deleteByIds(List<String> ids) { if (CollectionUtil.isEmpty(ids)) { return new DeleteResponse(); } final String idName = schema.getIdName(); Term[] terms = new Term[ids.size()]; int index = 0; for (String id : ids) { terms[index++] = new Term(idName, id); } try { if (logger.isDebugEnabled()) { logger.debug("deleting documents..."); } indexWriter.deleteDocuments(terms); updateCount.addAndGet(ids.size()); if (logger.isDebugEnabled()) { logger.debug("delete documents finish."); } } catch (IOException e) { logger.error("delete error", e); return new DeleteResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new DeleteResponse(); }
public OperationResponse commitAndOptimize() { try { if (logger.isDebugEnabled()) { logger.debug("commiting..."); } indexWriter.commit(); if (logger.isDebugEnabled()) { logger.debug("commit finish."); } if (logger.isDebugEnabled()) { logger.debug("optimizing..."); } indexWriter.forceMerge(defaultMergeSize); if (logger.isDebugEnabled()) { logger.debug("optimize finish."); } reopenSearcher(); } catch (IOException e) { logger.error("optimize error", e); return new OperationResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } catch (OutOfMemoryError e) { CloseUtil.close(indexWriter); logger.error("error of OOM", e); return new OperationResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new OperationResponse(); }
@Override public void close() { CloseUtil.close(indexSearcher); CloseUtil.close(indexReader); CloseUtil.close(indexWriter); CloseUtil.close(directory); opened.set(false); if (logger.isWarnEnabled()) { logger.warn("search engine has been closed."); } }
@Override public QueryResponse query(SearchQuery searchQuery) { try { if (logger.isDebugEnabled()) { logger.debug("searching query..."); } long start = System.currentTimeMillis(); QueryParser queryParser = new QueryParser( LuceneConfig.LUCENE_VERSION, schema.getDefaultSearchField(), schema.getAnalyzer()); Query query = queryParser.parse(searchQuery.getQuery()); int pageNo = searchQuery.getPageNo(); int pageSize = searchQuery.getPageSize(); int fullPageCount = pageNo * pageSize; int pageStartIndex = pageNo < 1 ? 0 : ((pageNo - 1) * pageSize); Sort sort = getSort(searchQuery); Filter filter = getFilter(searchQuery); TopFieldDocs topFieldDocs = indexSearcher.search(query, filter, fullPageCount, sort); ScoreDoc[] scoreDocs = topFieldDocs.scoreDocs; int scoreDocsLength = scoreDocs.length; List<OutputDocument> outputDocuments; if (scoreDocsLength <= pageStartIndex) { // 当前页没有数据了 outputDocuments = CollectionUtil.newArrayList(0); } else { // 只获取最后一页的数据 outputDocuments = CollectionUtil.newArrayList(scoreDocs.length - pageStartIndex); for (int i = pageStartIndex; i < scoreDocs.length; ++i) { Document doc = indexSearcher.doc(scoreDocs[i].doc); OutputDocument outputDocument = DocumentTransformUtil.toOutputDocument(doc, schema); outputDocuments.add(outputDocument); } } QueryResponse queryResponse = new QueryResponse(); queryResponse.setOutputDocuments(outputDocuments); queryResponse.setTotalHits(topFieldDocs.totalHits); if (logger.isDebugEnabled()) { logger.debug("search query finish."); } long end = System.currentTimeMillis(); long timeEscape = end - start; queryResponse.setTimeEscape(timeEscape); return queryResponse; } catch (Exception e) { logger.error("search query error", e); return new QueryResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } }
@Override public OperationResponse rollback() { try { if (logger.isDebugEnabled()) { logger.debug("rollbacking..."); } indexWriter.rollback(); if (logger.isDebugEnabled()) { logger.debug("rollback finish."); } } catch (IOException e) { logger.error("rollback error", e); return new OperationResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new OperationResponse(); }
@Override public OperationResponse reopen() { try { reopenSearcher(); } catch (IOException e) { logger.error("repen error", e); return new OperationResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new OperationResponse(); }
@Override public AddResponse add(InputDocument inputDocument) { try { if (logger.isDebugEnabled()) { logger.debug("adding document..."); } assertIdExist(inputDocument); Document document = DocumentTransformUtil.toLuceneDocument(inputDocument, schema); indexWriter.updateDocument( new Term(schema.getIdName(), document.getFieldable(schema.getIdName()).stringValue()), document, schema.getAnalyzer()); updateCount.incrementAndGet(); if (logger.isDebugEnabled()) { logger.debug("add document finish."); } } catch (IOException e) { return new AddResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new AddResponse(); }
protected void open(Directory directory) throws IOException { IndexWriter newIndexWriter = null; IndexReader newIndexReader = null; IndexSearcher newIndexSearcher = null; if (logger.isDebugEnabled()) { logger.debug("opening directory..."); } try { IndexWriterConfig indexWriterConfig = new IndexWriterConfig(LuceneConfig.LUCENE_VERSION, schema.getAnalyzer()); newIndexWriter = new IndexWriter(directory, indexWriterConfig); newIndexReader = IndexReader.open(newIndexWriter, true); newIndexSearcher = new IndexSearcher(newIndexReader); synchronized (this) { IndexWriter oldIndexWriter = this.indexWriter; IndexSearcher oldIndexSearcher = this.indexSearcher; IndexReader oldIndexReader = this.indexReader; this.indexWriter = newIndexWriter; this.indexSearcher = newIndexSearcher; this.indexReader = newIndexReader; CloseUtil.close(oldIndexSearcher); CloseUtil.close(oldIndexReader); CloseUtil.close(oldIndexWriter); } if (logger.isDebugEnabled()) { logger.debug("open directory finish."); } } catch (IOException e) { logger.error("open directory error", e); CloseUtil.close(newIndexSearcher); CloseUtil.close(newIndexReader); CloseUtil.close(newIndexWriter); throw e; } }
protected void reopenSearcher() throws IOException { try { reopenLock.lock(); if (updateCount.get() > 0) { logger.info("proccessing reopen..."); IndexReader oldIndexReader = this.indexReader; IndexSearcher oldIndexSearcher = this.indexSearcher; IndexReader newIndexReader = IndexReader.openIfChanged(oldIndexReader); if (newIndexReader != null) { IndexSearcher newIndexSearcher = new IndexSearcher(newIndexReader); indexSearcher = newIndexSearcher; indexReader = newIndexReader; CloseUtil.close(oldIndexReader); CloseUtil.close(oldIndexSearcher); } updateCount.set(0); logger.info("proccess reopen finish."); } else { logger.info("no thing to reopen"); } } finally { reopenLock.unlock(); } }
@Override public OperationResponse commit() { try { if (logger.isDebugEnabled()) { logger.debug("commiting..."); } indexWriter.commit(); if (logger.isDebugEnabled()) { logger.debug("commit finish."); } reopenSearcher(); } catch (IOException e) { logger.error("commit error", e); return new OperationResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } catch (OutOfMemoryError e) { CloseUtil.close(indexWriter); logger.error("error of OOM", e); // TODO reopen writer? return new OperationResponse(e.getMessage(), ResultCodes.COMMON_ERROR); } return new OperationResponse(); }