포켓몬으로 알아보는 루씬 (2) Boolean query

jinwook han·2022년 3월 2일
0

이번 글에서는 루씬으로 악 타입인 포켓몬을 검색하겠습니다.

@Test
void 악타입_포켓몬_쿼리() throws IOException {
// TODO
}

포켓몬 데이터 분석

포켓몬은 기본적으로 타입을 두 개 가지고 있습니다.
데이터는 다음과 같이 적재됩니다.

이름,type1,type2 ...
이상해씨,grass,poison ...
파이리,fire,,...

따라서 악타입인 포켓몬을 조회하려면,
type1이 dark 거나, type2가 dark인 포켓몬을 조회합니다.

Boolean query

이 때 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

검색을 하기 위해서는 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"));
  }
}

결과로 악타입 포켓몬 잘 필터링 되는 것을 확인할 수 있습니다.

elasticsearch 쿼리라면

lucene 쿼리로 elasticsearch 쿼리를 유추할 수 있습니다.
구조가 같기 때문입니다.
elasticsearch 쿼리라면 다음과 같이 표현할 수 있습니다.

{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "type1": "dark"
          }
        },
        {
          "term": {
            "type2": "dark"
          }
        }
      ]
    }
  }
}

0개의 댓글