Framework/Spring

[Spring] Elasticsearch에서의 MultiMatch: 다중 필드에 대한 매칭(feat. Java)- 컴도리돌이

컴도리돌이 2024. 10. 30. 09:00
728x90

ElasticSearch를 도입하고 데이터를 query DSL 방식으로 조회하는 데 도전하면서, 가장 많이 고민하게 되는 부분 중 하나가 바로 정확한 검색 결과를 어떻게 뽑아낼 것인가라는 문제였어요. 그중에서도 multiMatch는 여러 필드에서 검색어를 한 번에 매칭하게 도와주는 아주 유용한 쿼리랍니다. 이번 포스팅 글에서는 multiMatch 쿼리의 다양한 옵션을 소개하고, Java 코드로 구현하는 법까지 쭉 살펴보려고 합니다. 😊


Java 코드로 MultiMatch 구현하기

multiMatch 쿼리는 여러 필드를 한꺼번에 검색할 때 사용되는 쿼리입니다. 이를 통해 지정한 필드 중 하나라도 매칭되는 문서를 찾아낼 수 있어, 간편하면서도 다채로운 검색 결과를 얻을 수 있어요.

import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;

// 필드 리스트와 검색어
List<String> fieldList = Arrays.asList("field1", "field2");
String searchInput = "검색어";

// Bool 쿼리 생성
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery()
        .must(m -> m.bool(b -> {
            b.should(s -> s.bool(b2 -> b2.must(m2 -> m2.multiMatch(mm -> mm
                    .fields(fieldList)
                    .query(searchInput)
                    .type(MultiMatchQueryBuilder.Type.PHRASE)
            )).boost(50.0F)));
            ...
            return b;
        }));

// 쿼리 빌드
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.query(boolQuery);

MultiMatch 쿼리에서는 크게 다섯 가지 옵션을 제공하여 다양한 검색 조건을 설정할 수 있습니다. 각 옵션과 함께 실제 활용 예제를 하나씩 살펴볼게요!

type - 매칭 방식 지정

type 옵션을 통해 쿼리가 매칭되는 방식을 지정할 수 있어요. 아래는 각 타입과 그 의미입니다.

타입설명

best_fields 기본값, 가장 높은 점수를 가진 필드에서 검색어를 찾음
most_fields 매칭된 모든 필드 점수를 합산하여 검색 결과를 반환
cross_fields 여러 필드를 하나의 필드처럼 취급하여 검색
phrase 정확하게 일치하는 경우에만 매칭
phrase_prefix 접두사 일치를 지원
m2 -> m2.multiMatch(
        mm -> mm.fields(fieldList)
                .query(searchInput)
                .type(MultiMatchQueryBuilder.Type.PHRASE)
);

예를 들어, phrase 타입을 설정해 두고 "서울 종로구"를 검색하면 정확히 이 단어 순서로 일치하는 문서만 검색돼요. 😊


fuzziness - 오타 허용

fuzziness 옵션은 유사한 단어나 오타를 허용하고 검색 결과에 포함시킬 때 유용합니다. 오타가 흔한 환경이라면 매우 유용하죠.

예를 들어 "갱상남도 강산시 서장동"을 검색했을 때, fuzziness가 2로 설정되어 있다면 "경상남도 경산시 서상동"으로 유사한 결과를 찾아줄 수 있어요! 😉 아주 유연한 검색 기능이죠?

m2 -> m2.multiMatch(
        mm -> mm.fields(fieldList)
                .query(searchInput)
                .fuzziness("2") // 오타 2글자까지 허용
);

minimum_should_match - 최소 매칭 단어 수 설정

검색어의 최소 단어 수를 설정하는 minimum_should_match는 필드 간에 최소한의 매칭을 요구할 때 사용됩니다. 예를 들어 minimum_should_match("2")를 설정하면 field1과 field2에서 각각 최소 두 단어가 일치해야 결과로 나옵니다.

mn.multiMatch(
        mm -> mm.fields(fieldList)
                .query(searchInput)
                .minimumShouldMatch("2") // 최소 2개의 단어 일치
);

operator - 검색 연산자

검색 조건에 AND 또는 OR을 사용하여 검색의 조건을 강화할 수 있어요. 이 설정을 사용하면 "검색어 1"과 "검색어 2"가 모두 포함된 문서만 결과로 나옵니다.

m2 -> m2.multiMatch(
        mm -> mm.fields(fieldList)
                .query(searchInput)
                .operator(Operator.AND) // AND 연산자
);

고도화된 MultiMatch

고급 검색에서 여러 옵션을 조합하여 더 높은 품질의 결과를 추출할 수 있습니다. 아래는 multiMatch 쿼리의 다양한 옵션을 결합한 예제입니다.

m2 -> m2.multiMatch(
        mm -> mm.fields(fieldList)
                .query(searchInput)
                .type(MultiMatchQueryBuilder.Type.CROSS_FIELDS) // 여러 필드의 내용을 하나로 취급
                .fuzziness("AUTO") // 오타 허용 자동 조정
                .minimumShouldMatch("70%") // 70% 단어 일치
                .operator(Operator.OR) // OR 연산자
);

 

이 예제에서는 CROSS_FIELDS 타입을 사용해 모든 필드를 하나의 필드처럼 취급하여 검색하고, 오타는 자동으로 조정(AUTO)됩니다. 최소 70%의 단어가 일치할 경우에만 매칭하고, OR 연산자로 검색어의 유연성을 높였어요. 😊

 

이번 글을 통해 multiMatch 쿼리의 다양한 옵션을 어떻게 활용할 수 있을지 깊이 있게 살펴볼 수 있었습니다. 여러 조건을 유연하게 조합하는 방법을 배움으로써, 앞으로는 더 정교한 검색 조건을 구성할 수 있을 것 같아요. 또한 각 옵션이 사용자의 검색 의도에 맞는 결과를 만들어내는 과정이 정말 흥미로웠습니다. 😃

앞으로는 이 multiMatch 쿼리를 더욱 고도화하여 사용자에게 맞춤형 검색 경험을 제공하고, 상황에 맞는 새로운 조합 방식도 시도해 보고 싶습니다. 이번이 뜻깊은 시간이 되었고, 다음 프로젝트에도 큰 도움이 될 것 같습니다! 😊


 

Multi-match query | Elasticsearch Guide [8.15] | Elastic

The cross_fields type blends field statistics in a complex way that can be hard to interpret. The score combination can even be incorrect, in particular when some documents contain some of the search fields, but not all of them. You should consider the com

www.elastic.co