본문 바로가기
dev/elasticsearch

Elasticsearch 최신 데이터에 score 가중치 부여하기

by igooo 2025. 8. 18.
728x90

개요

Elasticsearch를 사용하여 검색할 때 정적 데이터를 기반으로 더 높은 score를 부여하고 싶을 때가 있다. 예를 들어 게시글 검색의 경우 최신 게시글에 더 높은 score를 부여하거나, 제품 검색의 경우 판매량이 높은 제품에 대하여 높은 score를 부여하는 경우다. (score를 사용하지 않고 sort를 사용하여 정렬하면 score는 무시하고 문서가 정렬되기 때문에 정확도는 떨어질 수 있다.)

 

Elasticsearch에는 정적 관련성 신호를 점수에 반영(Incorporating static relevance signals into the score)하는 두 가지 방법이 있다.

이번 게시글에는 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를 사용한 위 쿼리는 아래와 같이 구성되어 있다.

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

728x90