이번 글에서는 루씬으로 악 타입
인 포켓몬을 검색하겠습니다.
@Test
void 악타입_포켓몬_쿼리() throws IOException {
// TODO
}
포켓몬은 기본적으로 타입을 두 개 가지고 있습니다.
데이터는 다음과 같이 적재됩니다.
이름,type1,type2 ...
이상해씨,grass,poison ...
파이리,fire,,...
따라서 악타입인 포켓몬을 조회하려면,
type1이 dark 거나, type2가 dark인 포켓몬을 조회합니다.
이 때 Boolean query를 활용합니다.
Boolean query는 빌더로 만들며, add로 조건을 더할 수 있습니다.
BooleanQuery query = new BooleanQuery.Builder()
.add(쿼리, 조건유형)
.add(쿼리, 조건유형)
.build();
조건유형은 4가지입니다.(MUST, FILTER, SHOULD, MUST_NOT)
MUST, FILTER, SHOULD, MUST_NOT은 Elasticsearch에서 또한 자주 볼 수 있습니다.
type1이 dark타입 이거나 type2가 dark 타입인 포켓몬을 검색해야 하므로, SHOULD 조건 유형을 활용합니다.
type 이 dark 타입인지 여부는 term 쿼리를 활용합니다.
완성된 쿼리는 아래와 같습니다.
Term type1DarkTerm = new Term("type1", "dark");
TermQuery type1DarkTermQuery= new TermQuery(type1DarkTerm);
Term type2DarkTerm = new Term("type2", "dark");
TermQuery type2DarkTermQuery = new TermQuery(type2DarkTerm);
BooleanQuery query = new BooleanQuery.Builder()
.add(type1DarkTermQuery, BooleanClause.Occur.SHOULD)
.add(type2DarkTermQuery, BooleanClause.Occur.SHOULD)
.build();
검색을 하기 위해서는 IndexSearcher가 필요합니다.
File file = new File("hi"); // hi: 인덱싱된 루씬 데이터가 존재하는 로컬 경로
Directory directory = FSDirectory.open(file.toPath());
DirectoryReader directoryReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new `IndexSearcher(directoryReader);
IndexSearcher를 활용해 위에서 만든 BooleanQuery 를 실행합시다.
@Test
void 악타입만_필터링() throws IOException {
File file = new File("hi");
Directory directory = FSDirectory.open(file.toPath());
DirectoryReader directoryReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(directoryReader);
Term type1DarkTerm = new Term("type1", "dark");
TermQuery type1DarkTermQuery = new TermQuery(type1DarkTerm);
Term type2DarkTerm = new Term("type2", "dark");
TermQuery type2DarkTermQuery = new TermQuery(type2DarkTerm);
BooleanQuery query = new BooleanQuery.Builder()
.add(type1DarkTermQuery, BooleanClause.Occur.SHOULD)
.add(type2DarkTermQuery, BooleanClause.Occur.SHOULD)
.build();
TopDocs search = indexSearcher.search(query, 1000);
for (int i = 0; i < 50; i++) {`
Document doc = indexSearcher.doc(search.scoreDocs[i].doc);
System.out.println(doc.get("name"));
}
}
결과로 악타입 포켓몬 잘 필터링 되는 것을 확인할 수 있습니다.
lucene 쿼리로 elasticsearch 쿼리를 유추할 수 있습니다.
구조가 같기 때문입니다.
elasticsearch 쿼리라면 다음과 같이 표현할 수 있습니다.
{
"query": {
"bool": {
"should": [
{
"term": {
"type1": "dark"
}
},
{
"term": {
"type2": "dark"
}
}
]
}
}
}