๐Ÿงฎ ์ถ”์ฒœ์ˆœ ์ ์ˆ˜ ๊ณต์‹ ์ง์ ‘ ์„ค๊ณ„

์ด ๋ฌธ์„œ๋Š” Elasticsearch์—์„œ ์ถ”์ฒœ์ˆœ ์ •๋ ฌ์„ ์œ„ํ•ด ์ ์ˆ˜(score)๋ฅผ ์ˆ˜ํ•™์ ์œผ๋กœ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค.
BM25 ์ ์ˆ˜์™€ ์‚ฌ์šฉ์ž ํ–‰๋™ ๋ฐ์ดํ„ฐ(likes, clicks) ๊ทธ๋ฆฌ๊ณ  ์ตœ์‹ ์„ฑ์„ ์กฐํ•ฉํ•˜์—ฌ ์ถ”์ฒœ ์ ์ˆ˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


โœ… ๋ชฉํ‘œ ์ ์ˆ˜ ๊ณต์‹

์ตœ์ข… ์ ์ˆ˜ = BM25 ร— ์ธ๊ธฐ ์ ์ˆ˜ + ์ตœ์‹ ์„ฑ ์ ์ˆ˜
  • BM25: Elasticsearch ๊ธฐ๋ณธ ๊ฒ€์ƒ‰ ์ ์ˆ˜
  • ์ธ๊ธฐ ์ ์ˆ˜: likes, clicks๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ณ„์‚ฐ
  • ์ตœ์‹ ์„ฑ ์ ์ˆ˜: createdAt ํ•„๋“œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ decay ์ ์šฉ

1. ๐ŸŽฏ BM25 (๊ธฐ๋ณธ ์ ์ˆ˜)

  • ๊ธฐ๋ณธ์ ์œผ๋กœ match, multi_match ์ฟผ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•  ๊ฒฝ์šฐ BM25 ์ ์ˆ˜๊ฐ€ ์ž๋™ ๊ณ„์‚ฐ๋ฉ๋‹ˆ๋‹ค.
  • ์ •ํ™•๋„ ๊ธฐ๋ฐ˜ ๊ฒ€์ƒ‰์— ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
{
  "multi_match": {
    "query": "์นด์นด์˜ค",
    "fields": ["title^3", "content", "tags^2"]
  }
}

2. ๐Ÿ“ˆ ์ธ๊ธฐ ์ ์ˆ˜ ์ˆ˜์‹ (log1p, sqrt)

{
  "field_value_factor": {
    "field": "likes",
    "factor": 1.2,
    "modifier": "sqrt",
    "missing": 0
  }
},
{
  "field_value_factor": {
    "field": "clicks",
    "factor": 0.8,
    "modifier": "log1p",
    "missing": 1
  }
}
  • sqrt: ์ข‹์•„์š” ์ˆ˜์˜ ์ฆ๊ฐ€ํญ์„ ์™„ํ™”
  • log1p: ํด๋ฆญ ์ˆ˜๊ฐ€ ๋งŽ์•„๋„ ์™„๋งŒํ•˜๊ฒŒ ์ ์ˆ˜ ์ฆ๊ฐ€

3. ๐Ÿ•’ ์ตœ์‹ ์„ฑ ์ ์ˆ˜ (decay ํ•จ์ˆ˜)

{
  "gauss": {
    "createdAt": {
      "origin": "now",
      "scale": "10d",
      "decay": 0.4
    }
  }
}
  • createdAt ๊ธฐ์ค€์œผ๋กœ ์ ์ˆ˜ ๊ฐ์†Œ
  • ์ตœ์‹  ๋ฌธ์„œ์ผ์ˆ˜๋ก ์ ์ˆ˜๊ฐ€ ๋†’๊ณ  ์˜ค๋ž˜๋œ ๋ฌธ์„œ๋Š” ๋‚ฎ์•„์ง

4. โš™๏ธ score_mode / boost_mode ์„ค์ •

ํ•ญ๋ชฉ์„ค๋ช…
score_mode์—ฌ๋Ÿฌ function ์ ์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ๊ฒฐํ•ฉํ• ์ง€ (sum, avg ๋“ฑ)
boost_mode๊ธฐ์กด _score์™€ function ๊ฒฐ๊ณผ ๊ฒฐํ•ฉ ๋ฐฉ์‹

์ถ”์ฒœ ๊ณต์‹์— ๋งž๋Š” ์„ค์ •

"score_mode": "sum",
"boost_mode": "multiply"
  • ์ ์ˆ˜ ํ•จ์ˆ˜๋ผ๋ฆฌ๋Š” sum
  • ๊ทธ ๊ฒฐ๊ณผ๋ฅผ BM25 _score์™€ ร— (multiply)

5. ๐Ÿงช ์ „์ฒด ์˜ˆ์‹œ ์ฟผ๋ฆฌ

{
  "query": {
    "function_score": {
      "query": {
        "multi_match": {
          "query": "์นด์นด์˜ค",
          "fields": ["title^3", "content", "tags^2"]
        }
      },
      "functions": [
        {
          "field_value_factor": {
            "field": "likes",
            "factor": 1.2,
            "modifier": "sqrt",
            "missing": 0
          }
        },
        {
          "field_value_factor": {
            "field": "clicks",
            "factor": 0.8,
            "modifier": "log1p",
            "missing": 1
          }
        },
        {
          "gauss": {
            "createdAt": {
              "origin": "now",
              "scale": "10d",
              "decay": 0.4
            }
          }
        }
      ],
      "score_mode": "sum",
      "boost_mode": "multiply"
    }
  }
}

โœ… ์ •๋ฆฌ

์š”์†Œ์„ค๋ช…
BM25๊ธฐ๋ณธ ํ…์ŠคํŠธ ๋งค์นญ ์ ์ˆ˜
์ธ๊ธฐ ์ ์ˆ˜likes, clicks โ†’ sqrt, log1p ์ ์šฉ
์ตœ์‹ ์„ฑ ์ ์ˆ˜createdAt โ†’ decay ์ ์šฉ
์ตœ์ข… ์กฐํ•ฉscore_mode: sum, boost_mode: multiply