package com.intuit.tank.search.lucene; /* * #%L * Lucene Indexer * %% * Copyright (C) 2011 - 2015 Intuit Inc. * %% * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * #L% */ import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.lucene.document.Document; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.ScoreDoc; import org.apache.lucene.search.TopDocs; import org.apache.lucene.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; import com.intuit.tank.search.util.SearchConstants; public class LuceneService { private static final Logger LOG = LogManager.getLogger(LuceneService.class); private Directory directory; /** * Initializes the attributes of the instance of the class. Right now it uses the searchDirectory as the default * search index location. * * TODO: Fetch the search index location from the tank configuration file. * * @throws IOException */ public LuceneService() throws IOException { this(new SimpleFSDirectory(new File("./searchDirectory"))); } /** * initializes the attributes of the instance. * * @param directory */ LuceneService(Directory directory) { initialize(directory); } /** * Initializes the directory and analyzer to be used for search service. * * @param directory */ private void initialize(Directory directory) { this.directory = directory; } /** * Indexes a document * * @param doc */ public void indexDocument(Document doc) { indexDocuments(Arrays.asList(new Document[] { doc })); } /** * Indexes a list of documents. * * @param docs */ public void indexDocuments(List<Document> docs) { IndexWriter writer = getWriter(); for (Document document : docs) { try { writer.addDocument(document); } catch (Exception e) { e.printStackTrace(); closeWriter(writer); throw new RuntimeException(e); } } closeWriter(writer); } /** * Closes the writer after optimizing the writer. One must call the closeWriter after one is done performing * indexing on documents. * * @param writer */ private void closeWriter(IndexWriter writer) { try { writer.optimize(); writer.close(); } catch (Exception e1) { e1.printStackTrace(); // throw new RuntimeException(e1); } } /** * Removes the index of the document * * @param doc */ public void removeDocument(Query query) { removeDocuments(Arrays.asList(new Query[] { query })); } /** * Removes the indexes of the documents. * * @param docs */ public void removeDocuments(List<Query> queries) { IndexWriter writer = getWriter(); for (Query query : queries) { try { writer.deleteDocuments(query); } catch (Exception e) { e.printStackTrace(); closeWriter(writer); throw new RuntimeException(e); } } closeWriter(writer); } /** * Searches through the index for the specified query and returns the list of documents that finds a match for the * query. * * @param query * @return */ public List<Document> search(Query query, boolean prefixWildCard) { List<Document> documents = new ArrayList<Document>(); try { IndexSearcher searcher = getSearcher(); TopDocs search = searcher.search(query, 10000); for (ScoreDoc scoreDoc : search.scoreDocs) { Document doc = searcher.doc(scoreDoc.doc); documents.add(doc); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } return documents; } /** * Clears all the indices from the search index location; */ public void clearIndex() { IndexWriter writer = getWriter(); try { writer.deleteAll(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } finally { closeWriter(writer); } } /** * Gets a searcher for the search index location * * @return */ private IndexSearcher getSearcher() { IndexSearcher searcher = null; try { IndexReader reader = getReader(); if (!reader.isCurrent()) { reader.reopen(); } searcher = new IndexSearcher(reader); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(); } return searcher; } /** * Gets a new reader for the search index location * * @return */ private IndexReader getReader() { try { return IndexReader.open(directory); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * Gets a writer for the search index location * * @return */ private IndexWriter getWriter() { IndexWriter writer = null; try { IndexWriterConfig iwc = new IndexWriterConfig(SearchConstants.version, SearchConstants.analyzer); IndexWriter.unlock(directory); writer = new IndexWriter(directory, iwc); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } return writer; } }