개요
Elasticsearch를 사용하여 검색할 때 정적 데이터를 기반으로 더 높은 score를 부여하고 싶을 때가 있다. 예를 들어 게시글 검색의 경우 최신 게시글에 더 높은 score를 부여하거나, 제품 검색의 경우 판매량이 높은 제품에 대하여 높은 score를 부여하는 경우다. (score를 사용하지 않고 sort를 사용하여 정렬하면 score는 무시하고 문서가 정렬되기 때문에 정확도는 떨어질 수 있다.)
Elasticsearch에는 정적 관련성 신호를 점수에 반영(Incorporating static relevance signals into the score)하는 두 가지 방법이 있다.
- script_socre: https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-script-score-query
- rank_feature: https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-rank-feature-query
이번 게시글에는 rank_feature 쿼리를 사용하여 정적 데이터를 기반으로 score에 가중치를 부여하는 방법에 대하여 알아본다.
Getting Started
예제에서 게시글을 저장하는 index를 생성하여 rank_feature 쿼리 사용법에 대하여 알아본다.
Step 1: rank_feature 타입 알아보기
rank_feature 타입에 대한 상세한 설명은 공식 문서를 참고하고(https://www.elastic.co/docs/reference/elasticsearch/mapping-reference/rank-feature) 여기서는 간단히 사용법에 대하여 알아본다.
{
"mappings": {
"properties": {
"pagerank": {
"type": "rank_feature"
},
"url_length": {
"type": "rank_feature",
"positive_score_impact": false
},
"topics": {
"type": "rank_features"
}
}
}
}
작동 방식
- rank_feature 필드는 문서마다 하나의 양수/실수 값을 저장한다.
- 저장된 값은 문서 점수에 영향을 주는 요소로 작용한다. (가능하면 모든 문서에 값을 입력한다)
- rank_feature 필드는 오직 점수 계산용으로만 사용된다.
주요 설정 옵션
- positive_score_impact: 값이 클수록 문서의 점수가 높아진다. false로 설정하는 경우 값이 클수록 점수가 낮아진다. (default: true)
- rank_features: 여러 개의 특성(feature)을 하나의 필드에 저장할 수 있는 확장형 타입이다. (이름과 값의 쌍으로 구성된 map 형태)
Step 2: 게시글 저장을 위한 Mapping 설정
freshness_socre 필드를 추가하고 type은 rank_feature로 설정한다.
PUT /blog_posts
{
"mappings": {
"properties": {
"title": { "type": "text" },
"content": { "type": "text" },
"created_at": { "type": "date" },
"freshness_score": { "type": "rank_feature" }
}
}
}
Step 3: 게시글 저장
POST /blog_post/_doc
{
"title": "Spring Framework 7.0.0 소개",
"content": "이번 포스트에서는 Spring Framework 7.0.0의 새로운 기능을 소개한다...",
"created_at": "2025-08-20T20:01:12Z",
"freshness_socre": 30
}
freshness_score의 값은 게시글 작성 시간을 기준으로 최신 게시글일수록 높은 점수를 부여한다. rank_feature는 숫자 값을 기반으로 함으로 각 서비스에 원하는 방식을 사용하여 값을 설정한다.
예를 들어 시간값을 그대로 숫자로 변환하거나, 최고점을 설정하고 30일마다 점수를 감소시키는 방식 등 다양한 방식으로 서비스에 맞게 로직을 작성하여 값을 설정할 수 있다.
Step 4: rank_feature를 사용한 검색 쿼리
POST /blog_posts/_search
{
"query": {
"bool": {
"must": [
"match": {"title": "spring"}
]
},
"should": [
{
"rank_feature": {
"field": "freshness_score",
"boost": 0.1
}
}
]
}
}
rank_feature를 사용한 위 쿼리는 아래와 같이 구성되어 있다.
- must: 실제 검색어에 대한 매칭
- should: freshness_socre가 높은 문서에 추가 점수를 부여하도록 쿼리에 추가
- boost: freshness_socre를 사용하여 어떤 가중치 함수(https://www.elastic.co/docs/reference/query-languages/query-dsl/query-dsl-rank-feature-query#rank-feature-query-functions)를 사용하여 얼마나 가중치를 부여할지
should 구문에 유무에 따라서 검색 결과가 다른 것을 알 수 있다.
마무리
rank_feature를 사용하여 정적 데이터 기반으로 score에 가중치를 부여하는 방법에 대하여 알아봤다.
rank_feature를 사용하면 elasticsearch에 미리 정의된 함수(Saturation, Logarithm, Sigmoid, Linear)를 사용해서 점수를 계산하기 때문에 score 계산에 별도의 가중치 계산법을 사용하는 경우 유연성이 떨어질 수 있다. 반면 script_score 쿼리는 사용자 쿼리에 계산식을 추가하여 높은 유연성을 제공하지만 모든 문서에 대하여 스크립트를 실행해야 하므로 CPU 사용량이 높아지고 쿼리에 대하여 캐싱이 불가능하다.
rank_feature 쿼리는 elasticsaerch 내부적으로 최적화되어 있고 특별한 방식으로 인덱싱하여 경쟁력이 낮은 문서를 건너뛰고 쿼리에 상위 일치 항목을 더 빠르게 찾을 수 있도록 해준다.
참고
https://www.elastic.co/guide/en/elasticsearch/reference/8.18/static-scoring-signals.html
'dev > elasticsearch' 카테고리의 다른 글
Elasticsearch 숫자형 데이터 검색 성능 개선 (0) | 2025.08.05 |
---|---|
Elasticsearch stemming (어간 추출) (0) | 2025.02.19 |
Elasticsearch hybrid search with RRF(Reciprocal rank fusion) (0) | 2024.12.03 |
Elasticsearch 시맨틱 검색(semantic search) (1) | 2024.11.27 |
Elasticsearch - fuzzy query (0) | 2024.06.03 |