Computer Science/JAVA Lucene

Hello Lucene #1(HelloLucene main함수)

sgwon 2022. 3. 20. 17:16

대학교 강의로 java기반의 오픈소스인 Lucene을 이용하여 검색엔진을 만들어보게 되었다.

Maven을 사용하여 프로젝트를 구성하였고 

검색엔진 구조의 첫번째인 Tokenization&Normalization이 이루어지는 단계까지 구현한 코드를 보며 Lucene을 공부해보자.

IDE : Eclipse

JDK : 1.7.2

Maven : 1.7

Junit : 4.11

Lucene : 7.1.0


 

1. SimpleSE(인터페이스)

public interface SimpleSE {
	Directory createIndex(String[][] docs, Analyzer analyzer) throws IOException;	
	String[][] search(Directory index, String Querystr, Analyzer analyzer) throws IOException, org.apache.lucene.queryparser.classic.ParseException, ParseException;
}

인터페이스 파일을 먼저 만들어 미리 만들어야 할 메소드들을 정의시켰다. 혼자 기획하고 작업한다면 굳이 필요없겠지만,

회사처럼 cordinator와 developer의 역할이 나눠져 있는 상황에서는 서로 보기 쉽고 편하기 때문에 미리 익숙해져야 한다 하셨다.


 

2. main

public static void main(String[] args) throws IOException, ParseException, org.apache.lucene.queryparser.classic.ParseException{
    String docs[][] = {
        {"Lucene in Action", "193398817"},
        {"Lucene for Dummies", "55320055Z"},
        {"Managing Gigabytes", "55063552A"},
        {"The Art of Computer Science", "9900333X"}};

    HelloLucene se = new HelloLucene();

    // 1. create index & add docs
    Analyzer analyzer = new StandardAnalyzer();
    Directory index = se.createIndex(docs, analyzer);

    // 2. query
    String querystr = args.length > 0 ? args[0] : "lucene";

    // 3. search
    String[][] hits = se.search(index, querystr, analyzer);

    // 4. display results
    System.out.println("Found " + hits.length + "hits.");
    for(int i=0; i<hits.length; i++) System.out.println((i+1) + ". " + hits[i][0] + "\t" + hits[i][1]);
}

SimpleSE를 implements하는 HelloLucene의 메인함수이다. 여러 예외가 던져져있지만 나중에는 try구문을 한번 써보자(뭐가 무슨 예외인지 아직 모르니.)

코드를 먼저 읽기에 앞서 Tokenization이 어떤 건지 먼저 알아보자.

Tokenization이란 쉽게 말해 검색할 파일의 수많은 텍스트를 하나하나씩 나누는 과정이다. 나중에는 텍스트파일의 코드를 한 줄씩, 몇 번재 줄인지 알려주는 int 정수를 함께 넣어 

{{"What's it makes you frustrated?", 1}

,{"Lucene.", 2}

,{"....",3}

.

.

,{"text", n}}

같은 모양의 2중배열로 만드는 과정이다. 비록 위의 main에서는 미리 만들어져 있긴하지만 나중에 텍스트파일을 불러와 한줄씩 넣어줌으로써 만들 수 있다. 이 클래스는 이렇게 나누어진 배열에 접근하여 찾고자 하는 단어가 몇 번째 줄에 있는지 알아내는 간단한 클래스 이다.

이제 본격적으로 뜯어보자.


create index & add docs

// 1. create index & add docs
		Analyzer analyzer = new StandardAnalyzer();
		Directory index = se.createIndex(docs, analyzer);

1. Analyzer

 Lucene Analyzer(분석기)는 문서를 인덱싱하고 검색중에 텍스트를 분석하는데 사용한다. 주로 텍스트를 토큰으로 분류하며, 주로 토크나이저와 필터로 구성된다. 루씬 내부의 분석기는 총 코드의 StandardAnalyzer를 포함해 3개지만, 해당코드에서 사용하는 StandardAnalyzer만 알아보자.

 StandardAnalyzer는 가장 많이 사용하는 분석기로 URL과 이메일을 분석할 수 있다. 각 단어를 토큰으로 지정하고 영어의 관사나 구두점을 제거하고 인식한다. 아래 인덱스를 생성하는데 인덱스가 생성되면 쿼리와 인덱스를 이용하여 해당 인덱스를 검색할 수 있다.

Index

HelloLucene의 생성자로 선언된 se에 해당 클래스의 메소드인 createIndex(docs, analyzer)를 이용하여 검색할 데이터를 index로 Directory를 생성한다.

 


2. Query, Search, Display results

// 2. query
String querystr = args.length > 0 ? args[0] : "lucene";

// 3. search
String[][] hits = se.search(index, querystr, analyzer);

// 4. display results
System.out.println("Found " + hits.length + "hits.");
for(int i=0; i<hits.length; i++) System.out.println((i+1) + ". " + hits[i][0] + "\t" + hits[i][1]);

Query

쿼리라는 말은 막상 많이 들어봤다. 하지만 모호하게 알고 있어서 막연하게 느껴져서 이번에 한번 정의를 찾아보았다.

(출처 : http://www.terms.co.kr/query.htm)

위 이미지를 보면 해당코드에서 의 쿼리는 단순히 검색할 단어로 정의되어 있는 거 같다. 

본 코드의 메인함수는 args에서 검색할 키워드를 불러온다. 쿼리를 따로 args에 String으로 지정후 실행한다면 args[0]의 길이가 0이상이기 때문에 해당 문자열을 쿼리스트링으로 사용하게 되고, 만약 따로 쿼리를 넣지 않으면 논리연산자에 의해 "lucene"이 기본 쿼리로 들어가게 된다.(그래서 그냥 실행하면 lucene으로 시작하는 문자열이 두개 나온거였구나.)

 

Search

여기서 등장하는 hits라는 String 2중배열은 클래스메소드인 search(index, quertstr, analyzer)를 실행시켜 나온 결과 값을 저장하는 곳이다. 이것으로 search의 리턴값은 이중문자열배열이 되는데 쿼리로 찾은 문자열과 인덱스상의 문자열위치가 ','로 구분되어 길이가 2인 배열하나가 결과값 하나로 각각 저장됨을 유추할 수 있다.

 

Display results

쿼리를 "lucene"로 지정했을 경우

간단히 첫째줄에는 hit한 문장의 개수, 둘째 줄에는 각각의 문장을 출력하는데

hits배열의 [n][0]에는 n번째로 검색된 문장의 내용, [n][1]에는 해당문자의 인덱스번호가 저장되어 있음을 알 수 있다.

'Computer Science > JAVA Lucene' 카테고리의 다른 글

Hello Lucene#2(HelloLucene 메소드)  (0) 2022.03.20