[JAVA] 루씬 (Lucene 8.0.0)
오늘은 저녁/밤 내내 루씬을 공부했다.
0. 루씬(Lucene) 간략정리
– 강력한 색인과 검색 기능 지원
– 약 3MB 정도의 작은 라이브러리
– 창시자 더그 커팅은 하둡의 창시자이기도 함
– 루씬은 오직 색인과 검색에만 집중
— 루씬의 관심사 : 문서 텍스트 분석, 색인에 문서 추가, 색인, 질의 실행, 검색 질의 생성, 결과 출력
— 루씬이 관심 갖지 않는 것 : 검색 대상, 검색 대상 텍스트 확보, 분석 인터페이스, 관리 인터페이스, 검색 화면 인터페이스
– 루씬에서 발전/파생된 프로젝트에는 다음과 같은 것들이 있음
— 엘라스틱 서치, 솔라, 너치, 하둡
– 루씬 3점대 버전 책을 갖고 있는데, 3점대에서는 첫번째 글자에 와일드 카드(? 또는 *)를 넣을 수 없음.
— 이에 따라 가장 최신 버전인 8.0 버전으로 코드를 재작성함. 확인결과 첫번째 글자에도 와일드 카드 사용 가능.
1. 필요한 라이브러리 : lucene-core-8.0.0.jar
* 라이브러리 다운로드 주소 : https://mvnrepository.com/artifact/org.apache.lucene/lucene-core
2. 테스트 코드
특정 폴더(dataDir)에 txt 파일을 여러 개 넣어놓고, IndexManager.java 의 main 메서드를 실행한다.
그러면 색인 파일들이 결과폴더(indexDir)에 쌓인다.
이어서, SearchManager.java 의 main 메서드를 실행하여 파일 내용을 검색해본다.
2-1. IndexManager
|
package com.thkmon.lucene;
import java.io.File;
import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory;
public class IndexManager {
public static void main(String[] args) { IndexManager indexMng = new IndexManager(); indexMng.doIndex(); } /** * 색인하기 */ public void doIndex() { // 색인 결과파일 폴더 지정 String indexDir = “C:\\index”; // 색인할 txt 파일들이 있는 대상 폴더 지정 String dataDir = “C:\\개인폴더\\개발작업\\개인사이트제작”; Directory dir = null; IndexWriterConfig config = null; IndexWriter indexWriter = null; try { dir = FSDirectory.open(new File(indexDir).toPath()); config = new IndexWriterConfig(new StandardAnalyzer()); indexWriter = new IndexWriter(dir, config); File[] fileArr = new File(dataDir).listFiles(); int fileCount = fileArr.length; File file = null; for (int i=0; i<fileCount; i++) { file = fileArr[i]; if (file.isDirectory()) { continue; } if (file.isHidden()) { continue; } if (!file.exists()) { continue; } if (!file.canRead()) { continue; } if (file.getName().toLowerCase().endsWith(“.txt”)) { indexFile(indexWriter, file); } } System.out.println(indexWriter.numRamDocs()); } catch (Exception e) { e.printStackTrace(); } finally { try { if (indexWriter != null) { indexWriter.close(); } } catch (Exception e) { indexWriter = null; } try { if (dir != null) { dir.close(); } } catch (Exception e) { dir = null; } } }
public void indexFile(IndexWriter indexWriter, File file) throws Exception { Document doc = getDocument(file); indexWriter.addDocument(doc); } private Document getDocument(File file) throws Exception { String fileContent = FileReadUtil.readFileToString(file, “MS949”, ” “); Document doc = new Document(); doc.add(new TextField(“contents”, String.valueOf(fileContent), Field.Store.YES)); doc.add(new TextField(“filename”, String.valueOf(file.getName()), Field.Store.YES)); doc.add(new TextField(“fullpath”, String.valueOf(file.getCanonicalPath()), Field.Store.YES)); System.out.println(“canonicalPath : “ + file.getCanonicalPath()); System.out.println(“filename : “ + file.getName()); System.out.println(“fileContent : “ + fileContent); System.out.println(“====================”); return doc; } }
|
2-2. SearchManager.java
|
package com.thkmon.lucene;
import java.io.File;
import org.apache.lucene.document.Document; import org.apache.lucene.index.DirectoryReader; import org.apache.lucene.index.IndexReader; import org.apache.lucene.index.Term; import org.apache.lucene.search.IndexSearcher; import org.apache.lucene.search.Query; import org.apache.lucene.search.TopDocs; import org.apache.lucene.search.WildcardQuery; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory;
public class SearchManager {
public static void main(String[] args) { SearchManager searchMng = new SearchManager(); searchMng.doSearch(); } /** * 검색하기 */ public void doSearch() { // 색인 결과파일 폴더 지정 String indexDir = “C:\\index”; // 검색 키워드 String keyword = “*깨끗*만들자*”; Directory dir = null; IndexReader indexReader = null; IndexSearcher indexSearcher = null; try { dir = FSDirectory.open(new File(indexDir).toPath()); indexReader = DirectoryReader.open(dir); indexSearcher = new IndexSearcher(indexReader); // 정확한 어절을 검색하려면 TermQuery 객체 사용. // Query query = new TermQuery(new Term(“filename”, keyword)); // 와일드 카드(? 또는 *) 사용하여 검색하려면 WildcardQuery 객체 사용. Query query = new WildcardQuery(new Term(“filename”, keyword)); TopDocs docs = indexSearcher.search(query, 10); int docCount = 0; if (docs.scoreDocs != null) { docCount = docs.scoreDocs.length; System.out.println(docCount); Document doc = null; for (int i=0; i<docCount; i++) { doc = indexSearcher.doc(docs.scoreDocs[i].doc); System.out.println(doc.get(“contents”)); } } } catch (Exception e) { e.printStackTrace(); } finally { try { if (indexReader != null) { indexReader.close(); } } catch (Exception e) { indexReader = null; } try { if (dir != null) { dir.close(); } } catch (Exception e) { dir = null; } } } }
|
2-3. FileReadUtil.java
|
package com.thkmon.lucene;
import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.util.ArrayList;
public class FileReadUtil { /** * 파일 읽어서 ArrayList 로 리턴 * * @param file * @param encode * @return * @throws IOException * @throws Exception */ public static ArrayList<String> readFile(File file, String encode) throws IOException, Exception { if (file == null || !file.exists()) { return null; }
ArrayList<String> resultList = null;
FileInputStream fileInputStream = null; InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null;
try { fileInputStream = new FileInputStream(file); inputStreamReader = new InputStreamReader(fileInputStream, encode); bufferedReader = new BufferedReader(inputStreamReader);
String oneLine = null; while ((oneLine = bufferedReader.readLine()) != null) { if (resultList == null) { resultList = new ArrayList<String>(); }
resultList.add(oneLine); }
} catch (IOException e) { throw e;
} catch (Exception e) { throw e;
} finally { try { if (bufferedReader != null) { bufferedReader.close(); } } catch (Exception e) { bufferedReader = null; }
try { if (inputStreamReader != null) { inputStreamReader.close(); } } catch (Exception e) { inputStreamReader = null; }
try { if (fileInputStream != null) { fileInputStream.close(); } } catch (Exception e) { fileInputStream = null; } }
return resultList; } /** * 파일 읽어서 String 으로 리턴 * * @param file * @param encode * @param delimiter * @return * @throws IOException * @throws Exception */ public static String readFileToString(File file, String encode, String delimiter) throws IOException, Exception { StringBuffer buff = new StringBuffer(); ArrayList<String> strList = readFile(file, encode); if (strList != null && strList.size() > 0) { int listCount = strList.size(); for (int i=0; i<listCount; i++) { buff.append(strList.get(i)); buff.append(delimiter); } } return buff.toString(); } }
|