๐Ÿ› ๏ธ ๋งคํ•‘ + Analyzer + ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ์ข…ํ•ฉ ์‹ค์Šต

์ด ๋ฌธ์„œ๋Š” Elasticsearch์—์„œ posts ์ธ๋ฑ์Šค๋ฅผ ๋Œ€์ƒ์œผ๋กœ
๋งคํ•‘ ์„ค๊ณ„, custom analyzer ๊ตฌ์„ฑ, ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ์‹ค์Šต์„ ์ข…ํ•ฉ์ ์œผ๋กœ ์—ฐ์Šตํ•˜๊ธฐ ์œ„ํ•œ ์‹ค์ „ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.


1. ๐ŸŽฏ ๋ชฉํ‘œ ์š”์•ฝ

  • ์ปค์Šคํ…€ analyzer๋ฅผ ์ ์šฉํ•œ posts ์ธ๋ฑ์Šค ์ƒ์„ฑ
  • title, tags, content ํ•„๋“œ๋ฅผ ์ ์ ˆํžˆ text/keyword๋กœ ๊ตฌ์„ฑ
  • ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ์—์„œ match, filter, sort, search_after ๋“ฑ ์‹ค์ œ ํ™œ์šฉ

2. โš™๏ธ ์ปค์Šคํ…€ Analyzer + ๋งคํ•‘ ์˜ˆ์ œ

PUT http://localhost:9200/posts
{
  "settings": {
    "analysis": {
      "tokenizer": {
        "my_nori_tokenizer": {
          "type": "nori_tokenizer",
          "decompound_mode": "mixed"
        }
      },
      "filter": {
        "my_pos_filter": {
          "type": "nori_part_of_speech",
          "stoptags": ["E", "IC", "J"]
        },
        "my_stop_filter": {
          "type": "stop",
          "stopwords": ["์€", "๋Š”", "์ด", "๊ฐ€"]
        }
      },
      "analyzer": {
        "my_korean_analyzer": {
          "type": "custom",
          "tokenizer": "my_nori_tokenizer",
          "filter": [
            "lowercase",
            "my_pos_filter",
            "my_stop_filter"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "my_korean_analyzer",
        "fields": {
          "raw": { "type": "keyword" }
        }
      },
      "tags": {
        "type": "keyword"
      },
      "content": {
        "type": "text",
        "analyzer": "my_korean_analyzer"
      },
      "author": {
        "type": "keyword"
      },
      "created_at": {
        "type": "date"
      }
    }
  }
}

3. ๐Ÿ“ฆ ์˜ˆ์‹œ ๋ฌธ์„œ ์‚ฝ์ž… (Bulk API)

POST http://localhost:9200/posts/_bulk
{ "index": {} }
{ "title": "์นด์นด์˜คํŽ˜์ด ์„œ๋น„์Šค ์ถœ์‹œ", "tags": ["fintech", "kakao"], "content": "์นด์นด์˜ค์˜ ์ƒˆ๋กœ์šด ๊ฐ„ํŽธ๊ฒฐ์ œ ์„œ๋น„์Šค๊ฐ€ ์‹œ์ž‘๋˜์—ˆ์Šต๋‹ˆ๋‹ค.", "author": "alice", "created_at": "2024-01-01T10:00:00Z" }
{ "index": {} }
{ "title": "๋„ค์ด๋ฒ„ ์ง€๋„ ์—…๊ทธ๋ ˆ์ด๋“œ", "tags": ["map", "naver"], "content": "์ง€๋„ ๊ฒ€์ƒ‰์ด ๋” ๋น ๋ฅด๊ณ  ์ •ํ™•ํ•ด์กŒ์Šต๋‹ˆ๋‹ค.", "author": "bob", "created_at": "2024-02-15T12:30:00Z" }
{ "index": {} }
{ "title": "๊ตฌ๊ธ€ ๊ฒ€์ƒ‰ AI ๋„์ž…", "tags": ["ai", "google"], "content": "AI๋กœ ๋” ๋˜‘๋˜‘ํ•œ ๊ฒ€์ƒ‰์ด ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค.", "author": "charlie", "created_at": "2024-03-10T15:00:00Z" }

4. ๐Ÿ” ๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ์˜ˆ์ œ

๐ŸŽฏ 4-1. ์นด์นด์˜ค๋ฅผ ํฌํ•จํ•˜๊ณ  fintech ํƒœ๊ทธ๋ฅผ ๊ฐ€์ง„ ๋ฌธ์„œ ๊ฒ€์ƒ‰

POST http://localhost:9200/posts/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "content": "์นด์นด์˜ค" } }
      ],
      "filter": [
        { "term": { "tags": "fintech" } }
      ]
    }
  }
}

๐Ÿงญ 4-2. ์ •๋ ฌ + search_after๋ฅผ ์‚ฌ์šฉํ•œ ํŽ˜์ด์ง• ๊ฒ€์ƒ‰

POST http://localhost:9200/posts/_search
{
  "size": 2,
  "query": {
    "match_all": {}
  },
  "sort": [
    { "created_at": "desc" },
    { "_id": "asc" }
  ],
  "search_after": ["2024-01-01T10:00:00Z", "doc_id_2"]
}

๐Ÿ” 4-3. title ์ •๋ ฌ (multi-field ์‚ฌ์šฉ)

POST http://localhost:9200/posts/_search
{
  "query": {
    "match": {
      "title": "๊ฒ€์ƒ‰"
    }
  },
  "sort": [
    { "title.raw": "asc" }
  ]
}

โœ… ์š”์•ฝ

ํ•ญ๋ชฉ์„ค๋ช…
custom analyzer ์„ค์ •nori tokenizer + ๋ถˆ์šฉ์–ด + ํ’ˆ์‚ฌ ํ•„ํ„ฐ ์ ์šฉ
multi-field ๊ตฌ์„ฑtitle์€ text + keyword ํ•จ๊ป˜ ์‚ฌ์šฉ (raw ์ •๋ ฌ์šฉ)
๊ฒ€์ƒ‰ ์ฟผ๋ฆฌ ํ™œ์šฉmatch, filter, sort, search_after ์กฐํ•ฉ
Bulk ์‚ฝ์ž…๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋น ๋ฅธ ์‚ฝ์ž