검색결과 리스트
색인클래스에 해당되는 글 2건
- 2011.03.08 루씬과 색인,검색 클래스 사용예(Java)
- 2011.03.08 색인과 검색 주요 클래스
글
루씬과 색인,검색 클래스 사용예(Java)
인덱싱 클래스 ATIndexer
인덱싱 데이터는 트위터에서 수집한 status 데이터를 별도 저장한 텍스트 파일을 사용하였으며,
한건의 트윗글에 대해 status_id(글번호), text(내용), user_id(사용자번호), user_name(사용자이름)
데이터만 사용하였다.
루씬이 제공하는 필드에 따라 인덱싱하는 방법을 표현하기 각 데이터에 대해 다음과 같은 필드생성 옵션을 주었다.
status_id : Field.UnStored 를 사용. 분석과 검색을 수행하지만, 저장되지 않기 때문에 검색결과에서 보여줄 수는 없음
text : Field.Text 를 사용. 분석과 검색, 저장을 허용하여, 검색결과로 원문을 보여줄 수 있다.
user_id : Field.UnIndexed 를 사용. 검색어로 사용할 수 없지만, 다른 필드의 검색결과에서 같이 보여질 수 있다.user_name : Field.Keyword 를 사용. 분석을 하지 않지만, 검색과 저장을 한다. 검색시 이 필드는 분석되면 않되기
때문에 직접 텀쿼리를 만들어 IndexSearcher의 search 메소드에 전달해야한다.
인데싱에 사용한 파일(crawled_text.data)의 포맷
... status_id:2147483648 text:@NicoleLapin so many buttons user_id:12 user_name:Jack Dorsey status_id:2147483648 text:In alaska for the longest day of the year with Delphine and eWee. Seaplanes. Sunshine. user_id:14 user_name:noah glass ...
소스 : ATIndexer.java
package net.game.lucene.study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
// IndexSearcher
// Term
// Query
// TermQuery, RangeQuery, PrefixQuery, BooleanQuery, PharaseQuery, WildcardQuery, FuzzyQuery
// Hits
public class ATSearcher {
private String indexDir;
private IndexSearcher indexSearcher;
private Analyzer analyzer;
private Logger log = Logger.getLogger(ATSearcher.class);
public ATSearcher(String indexDir, Analyzer analyzer) throws IOException {
BasicConfigurator.configure();
this.indexDir = indexDir;
this.analyzer = analyzer;
this.indexSearcher = new IndexSearcher(this.indexDir);
}
public Hits search(String field, String searchWord) throws Exception {
Hits hits;
// user_name필드는 직접 텀쿼리를 생성하여 전달해야 올바른 검색결과를 얻을 수 있음
if (field.equals("user_name")) {
hits = this.indexSearcher.search(new TermQuery(new Term(field, searchWord)));
} else {
Query query = QueryParser.parse(searchWord, field, this.analyzer);
hits = this.indexSearcher.search(query);
}
return hits;
}
public static void main(String[] args) throws Exception {
BasicConfigurator.configure();
ATSearcher searcher = new ATSearcher("/Users/hiddenviewer/index_lucene", new StandardAnalyzer());
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("<검색필드:검색어> 입력! (종료: quit)");
while ((line = br.readLine()) != null) {
if (line.startsWith("quit")) {
System.out.println("ATIndexer Test 프로그램 종료!");
break;
}
int delimIndex = line.indexOf(":");
if (delimIndex == -1) {
System.out.println("<검색필드:검색어> 포맷으로 입력해주세요");
continue;
}
Hits hits = searcher.search(line.substring(0, delimIndex), line.substring(delimIndex+1));
System.out.println("------------------------------------------");
System.out.format("검색결과 개수: %d \n", hits.length());
System.out.println("------------------------------------------");
for (int i = 0; i < hits.length(); i++) {
Document d = hits.doc(i);
System.out.format("%20s: %s \n", "status_id", d.get("status_id"));
System.out.format("%20s: %s \n", "text", d.get("text"));
System.out.format("%20s: %s \n", "user_id", d.get("user_id"));
System.out.format("%20s: %s \n", "user_name", d.get("user_name"));
}
}
}
}
검색 클래스 ATSearcher
ATIndexer 가 인덱싱한 색인파일에서 검색을 하기 위해서 필드명:검색어 형태로 입력을 받는다. 필드명에 해당하는 필드에서
검색어가 포함된 도큐먼트를 찾아 검색결과를 출력해준다. 이때 중요한 것은 인덱싱 과정에서 Field.UnIndexed 로 지정한 user_id 필드는
검색어를 통해 검색할 수 없으며, 다른 필드를 통한 검색결과에만 포함되어 나온다. 또 Field.UnStored로 지정한 status_id 는 글번호로 검색은
가능하지만, 원문을 저장하고 있지 않기 때문에 결과에는 원문이 출력되지 않는다. Field.Keyword 로 지정한 user_name은 인덱싱과정에서분석이 되지 않기 때문에, 검색과정에서도 분석기에 의해서 분석되면 안된다. 검색필드가 user_name 인 경우에는 텀쿼리를 직접생성하여
IndexSearcher의 search 메소드에 전달해줘야 올바른 결과를 얻을 수 있다.
소스 : ATSearcher.java
package net.game.lucene.study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
// IndexSearcher
// Term
// Query
// TermQuery, RangeQuery, PrefixQuery, BooleanQuery, PharaseQuery, WildcardQuery, FuzzyQuery
// Hits
public class ATSearcher {
private String indexDir;
private IndexSearcher indexSearcher;
private Analyzer analyzer;
private Logger log = Logger.getLogger(ATSearcher.class);
public ATSearcher(String indexDir, Analyzer analyzer) throws IOException {
BasicConfigurator.configure();
this.indexDir = indexDir;
this.analyzer = analyzer;
this.indexSearcher = new IndexSearcher(this.indexDir);
}
public Hits search(String field, String searchWord) throws Exception {
Hits hits;
// user_name필드는 직접 텀쿼리를 생성하여 전달해야 올바른 검색결과를 얻을 수 있음
if (field.equals("user_name")) {
hits = this.indexSearcher.search(new TermQuery(new Term(field, searchWord)));
} else {
Query query = QueryParser.parse(searchWord, field, this.analyzer);
hits = this.indexSearcher.search(query);
}
return hits;
}
public static void main(String[] args) throws Exception {
BasicConfigurator.configure();
ATSearcher searcher = new ATSearcher("/Users/hiddenviewer/index_lucene", new StandardAnalyzer());
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("<검색필드:검색어> 입력! (종료: quit)");
while ((line = br.readLine()) != null) {
if (line.startsWith("quit")) {
System.out.println("ATIndexer Test 프로그램 종료!");
break;
}
int delimIndex = line.indexOf(":");
if (delimIndex == -1) {
System.out.println("<검색필드:검색어> 포맷으로 입력해주세요");
continue;
}
Hits hits = searcher.search(line.substring(0, delimIndex), line.substring(delimIndex+1));
System.out.println("------------------------------------------");
System.out.format("검색결과 개수: %d \n", hits.length());
System.out.println("------------------------------------------");
for (int i = 0; i < hits.length(); i++) {
Document d = hits.doc(i);
System.out.format("%20s: %s \n", "status_id", d.get("status_id"));
System.out.format("%20s: %s \n", "text", d.get("text"));
System.out.format("%20s: %s \n", "user_id", d.get("user_id"));
System.out.format("%20s: %s \n", "user_name", d.get("user_name"));
}
}
}
}
ATSearcher 실행결과
결과를 보면 Field.UnStored로 지정된 필드 status_id는 원문이 출력되지 않는 걸 알수 잇다.
'검색엔진로그' 카테고리의 다른 글
| [Lucene] java.lang.OutOfMemoryError : Java heap space (0) | 2011.03.15 |
|---|---|
| 루씬과 색인,검색 클래스 사용예(Java) (0) | 2011.03.08 |
| 색인과 검색 주요 클래스 (0) | 2011.03.08 |
| 로봇 프로토콜 (0) | 2011.03.07 |
설정
트랙백
댓글
글
색인과 검색 주요 클래스
Apache OpenSource Project인 Lucene 을 구성하는 색인과 검색과 관련된 주요 클래스를 알아보자.
색인 주요 클래스
색인과정 중에 사용되는 주요 클래스는 다음과 같다.
| 클래스 | 설명 |
|---|---|
| IndexWriter | 색인을 생성하고, 색인에 도큐먼트를 추가한다. |
| IndexReader | 색인에서 도큐먼트를 삭제한다 |
| Directory |
색인의 저장소. 일반적으로 파일시스템 FSDirectory와 메모리 RAMDirectory가 있다. 루씬 샌드박스에서 제공하는 데이터베이스를 색인의 저장소로 사용하는 JDBCDirectory 도 있다. |
| Analyzer |
내용을 텀 단위로 분리하는 역할을 하며, 색인과 검색 단계에서 동일한 분석기가 적용되야 올바른 검색결과를 얻을 수 있다. |
| Document |
검색을 위한 정보 구성의 단위가 된다. 하나의 메일 메시지 또는 하나의 웹페이지가 도큐먼트가 될수 있으며, 비지니스 로직에 따라 변경된다. |
| Field |
도큐먼트 내에서 정보를 검색하는 대상(카테고리)이다. 분석의 여부, 검색 가능여부, 저장하는지 여부에 따라 Keyword, UnIndexed, UnStored, Text 필드로 구분된다. 이러한 구분의 검색과 검색결과로 보여질 데이터의 항목들을 명확히 하여, 검색의 질과 효율을 높이기 위함이다. |
색인은 양질의 검색결과를 얻을 수 있도록 하는 근본이 되는 과정이다. 도큐먼트는 색인과 검색과정에서 정보의 저장과 검색의 단위가 되기 때문에, 어떠한 데이터들을 하나의 도큐먼트로 구성할지가 중요한 요소가 된다.
도규먼트를 구성하는 필드들은 다음과 같은 값들 일 수 있다.
| 필드 | 분석 | 검색 | 저장 | 사용 용도 |
|---|---|---|---|---|
| Field.Keyword | X | O | O | 변경되지 않는 고유정보 저장하기 위해 사용됨. 예) 파일의 경로, 메일번호, 게시물 번호 |
| Field.UnIndexed | X | X | O | 검색의 결과로 보여주기 위해서만 사용되는 정보. 예) 웹페이지 글의 상위 네번째줄까지 글.... |
| Field.UnStored | O | O | X | 검색의 대상이 되지만, 화면에는 보여질 필요가 없는 정보. 예) 웹문서의 태그... |
| Field.Text | O | O |
String(O) Reader(X) |
String 타입은 내용이 색인에 저장되고, Reader 타입은 내용이 색인에 저장되지 않는데, Reader는 불필요하게 많은 데이터를 저장하여 효율을 저하시킬 수 있기때문에 저장하지 않는다. |
검색 주요 클래스
검색과정 중에 사용되는 주요 클래스는 다음과 같다.
| 클래스 | 설명 |
|---|---|
| IndexSearcher |
색인에서 검색어를 찾아 결과를 반환하는 클래스. 검색단계에서도 검색어를 분석하는데 Analyzer 가 사용된다. 이때 색인단계와 검색단계에서 동일한 텀이 생성되게 하는 것은 루씬 라이브러리를 사용하는 개발자의 몫이다. |
| Term | 매칭이 되는 가장 최소단위의 단어이다. 색인과 검색과정에서 (필드이름, 단어) 의 쌍으로 구성된다. |
| Query |
루씬엔진이 해석할 수 있도록 검색의 조건을 변환한 클래스이다. TermQuery, RangeQuery, PrefixQuery 등 다양한 조건에 해당하는 Query문이 존재한다. 개발자는 사용자에게 적절한 검색인터페이스를 제공하여, 올바른 Query 을 생성해야한다 |
| QueryParser | 다양한 조건을 좀더 편리하게 문자열 조건문 형태로 입력받고, 이 문자열을 Query 서브클래스들의 조합으로 변환한다. |
| Hits |
IndexSearcher 클래스의 search 메소드의 검색결과 매칭된 도큐먼트들을 가지고 있는 결과객체이다. 실제 문서의 내용이 아닌 문서에 대한 ID 만을 가지고 있어서, 실제로 요청할 때 해당 도큐먼트를 디스크에서 로드해서 반환한다. |
'검색엔진로그' 카테고리의 다른 글
| [Lucene] java.lang.OutOfMemoryError : Java heap space (0) | 2011.03.15 |
|---|---|
| 루씬과 색인,검색 클래스 사용예(Java) (0) | 2011.03.08 |
| 색인과 검색 주요 클래스 (0) | 2011.03.08 |
| 로봇 프로토콜 (0) | 2011.03.07 |