미식가의 개발 일기

[Elasticsearch] 엘라스틱서치 인덱싱 본문

Elasticsearch

[Elasticsearch] 엘라스틱서치 인덱싱

대체불가 핫걸 2025. 7. 6. 22:47
엘라스틱서치에서 인덱스란?
데이터를 저장하는 공간으로 매핑을 통해 데이터 구조를 정의할 수 있다.

 

📖 인덱스 생성 구조

  • 해당 API로 PUT 요청을 보내면 새로운 인덱스가 생성된다. 
PUT : https://ip:9200/index_name
  • 인덱스 생성을 위해서는 JSON body에 2가지를 정의해야 한다.
    • `settings`: 클러스터, 인덱스 운영 설정(샤드 개수, 복제본 수, 텍스트 분석기 정의(커스텀 필터 등록) 등)
    • `mappings`: 필드 이름과 데이터 타입 지정

해당 예제는 커스텀 analyzer인 `my_analyzer``standard` tokenizer로 모든 단어를 분리하고, `lowercase` filter를 적용해 모든 단어를 소문자로 변환하도록 지정한다.
`title``content` 필드에 해당 커스텀 analyzer를 적용하고, id는 검색에 사용하지 않도록 `index: false`로 정의되었다.

{
    "settings": {
        "analysis": {
            "analyzer": {
                "my_analyzer": {
                    "type": "custom",
                    "char_filter": [],
                    "tokenizer": "standard",
                    "filter": ["lowercase"]
                }
            },
            "char_filter": {

            },
            "tokenizer": {
                "standard": {
                    "type": "standard"
                }
            },
            "filter": {
                "lowercase": {
                    "type": "lowercase"
                }
            }
        }
    },

    "mappings": {
        "properties": {
            "id": {
                "type": "long",
                "index": false
            },
            "title": {
                "type": "text",
                "analyzer": "my_analyzer"
            },
            "content": {
                "type": "text",
                "analyzer": "my_analyzer"
            }
        }
    }
}

 

※ elastic 공식 인덱스 생성 가이드 

 

analyzer | Reference

The analyzer parameter specifies the analyzer used for text analysis when indexing or searching a text field. Unless overridden with the search_analyzer...

www.elastic.co

 

분석기 테스트

GET : https://ip:9200/index_name/_analyze
{
  "analyzer": "my_analyzer",
  "text": "안녕하세요. 테스트 문장입니다."
}

 

📖 nori tokenizer 

앞서 사용한 standard tokenizer는 단순 띄어쓰기 및 문장 부호 기준 토큰화를 진행하므로 한글의 조사나 어미를 잘 처리하지 못한다. 

따라서 한글을 처리할 때는 nori tokenizer를 주로 사용한다.

 

1. 엘라스틱서치 컨테이너 접속

sudo docker exec -it es /bin/bash

 

 

2. nori 분석기 설치

bin/elasticsearch-plugin install analysis-nori

 

 

3. 엘라스틱서치 컨테이너 재시작

sudo docker restart es

 

 

4. setting에 nori tokenizer 추가

  • `decompound_mode`: 복합어 분해 방법 
    • `none`: 분해 X
    • `discard`: 분해해서 버림
    • `mixed`: 분해해서 포함 (복합어 + 원어) 
  • `discard_punctuation`: 문장 부호를 제거할지 여부 (`true`, `false`)
  • `lenient`: 오류에 관대하게 동작할지 여부 (`true`, `false`)
"settings": {
    "analysis": {
        "analyzer": {
            "my_analyzer": {
                "type": "custom",
                "char_filter": [],
                "tokenizer": "nori",
                "filter": ["lowercase"]
            }
        },
        "char_filter": {

        },
        "tokenizer": {
            "nori": {
                "type": "nori_tokenizer",
                "decompound_mode": "mixed",
                "discard_punctuation": true,
                "ienient": true

            }
        },
        "filter": {
            "lowercase": {
                "type": "lowercase"
            }
        }
    }
}

 

📖 사용자 사전 기반 tokenizer 

 

특정 단어들만 커스텀하여 분해하고 싶다면 사용자 사전을 사용하면 된다. 

 

1. 컨테이너 외부에 userdict.txt 생성

  • 컨테이너 내부에 두면 임사 파일로 처리되며 유지, 접근이 어렵다.

mkdir elastic_dict
cd elastic_dict

touch userdict.txt

 

 

2. 기존 컨테이너 제거 후 새로 생성

  • 제거
sudo docker stop es
sudo docker rm es

 

 

  • 재생성
sudo docker run -d --restart unless-stopped \
  --name es \
  -v /home/mingd/elastic_dict/:/usr/share/elasticsearch/config/dict/ \ # 여기에 경로 추가 
  -p 9200:9200 -p 9300:9300 \
  --network myes \
  -e "discovery.type=single-node" \
  -e "ES_JAVA_OPTS=-Xms2g -Xmx2g" \
  docker.elastic.co/elasticsearch/elasticsearch:8.17.2

 

  • 비밀번호 재설정
sudo docker exec -it es /bin/bash

bin/elasticsearch-setup-passwords interactive

 

  • nori 분석기 재설치 
bin/elasticsearch-plugin install analysis-nori

sudo docker restart es

 

 

3. settings 수정 

"settings": {
    "analysis": {
        "analyzer": {
            "my_analyzer": {
                "type": "custom",
                "char_filter": [],
                "tokenizer": "nori",
                "filter": ["lowercase"]
            }
        },
        "char_filter": {

        },
        "tokenizer": {
            "nori": {
                "type": "nori_tokenizer",
                "decompound_mode": "mixed",
                "discard_punctuation": true,
                "ienient": true,
                "user_dictionary": "dict/userdict.txt" # 여기에 경로 추가 

            }
        },
        "filter": {
            "lowercase": {
                "type": "lowercase"
            }
        }
    }
}

 

4. userdict.txt 작성

  • txt 파일 수정 후에는 컨테이너 재시작 필수

 

📖 동의어 사전 기반 filter

문장 분해가 끝나면 filtering 작업을 해주는데 동의어 사전을 만들어 특정 단어를 치환, 확장한다.

 

⚠️ 주의사항 (tokenizer와 synonym filter 충돌)

  • 동의어 필터는 tokenizer 이후에 적용된다.
  • 따라서, 동의어 사전에 정의된 단어들이 tokenizer에서 정확히 분리되는 단위와 일치해야 한다.
  • 예를 들어:
    • tokenizer가 "운동화"를 "운동", "화"로 나눈다면,
      동의어 사전에서 "운동화 => 스니커즈"로 지정해도 작동하지 않음.
    • 이 경우 "운동화"가 하나의 token으로 유지되도록 사용자 사전에 등록해야 동의어 필터가 적용 가능.

✅ 따라서 동의어로 처리할 단어는 tokenizer에서 분리되지 않도록 사용자 사전에 미리 정의해두어야 한다.

 

 

1. 컨테이너 외부에 userdict.txt 생성

※ 위에서 폴더 만들고 마운트 했으므로 엘라스틱 컨테이너 재성성하지 않아도 됨 

cd elastic_dict

touch synonym.txt

 

2. settings 수정

"settings": {
    "analysis": {
        "analyzer": {
            "my_analyzer": {
                "type": "custom",
                "char_filter": [],
                "tokenizer": "nori",
                "filter": ["lowercase", "synonym"] # 여기에 추가 
            }
        },
        "char_filter": {},
        "tokenizer": {
            "nori": {
                "type": "nori_tokenizer",
                "decompound_mode": "mixed",
                "discard_punctuation": true,
                "ienient": true,
                "user_dictionary": "dict/userdict.txt"
            }
        },
        "filter": {
            "lowercase": {
                "type": "lowercase"
            },
            # 여기에 추가 
            "synonym": {
                "type": "synonym",
                "synonyms_path": "dict/synonym.txt",
                "lenient": true
            }
        }
    }
}

 

3. synonym.txt 작성

  • txt 파일 수정 후에는 컨테이너 재시작 필수
확장
ai, 인공지능, artificial intelligence
택배, 배송, 배달
휴대폰, 스마트폰, 모바일

 

치환
이메일 => 메일
핸드폰 => 휴대폰
노트북컴퓨터 => 노트북

 

택배를 검색하면 type이 synonym인 배송, 배달이 함께 검색되고, 이메일 > 메일로 검색되는 것을 확인할 수 있다. 

 

 

반응형