Mapping
Mapping 카테고리의 모든 포스트 - 한국어
3개의 포스트
🎯 매핑 설계 잘하는 팁 & 전략
이 문서는 Elasticsearch에서 매핑(mapping)을 효율적으로 설계하기 위한 팁과 개념들을
http://localhost:9200/contents
기준으로 설명합니다.
1. 🎯 매핑 설계 잘하는 팁
🧹 불필요한 필드 제거
- 저장할 필요가 없는 데이터는 매핑 자체를 하지 않거나
_source
에서 제외 - 검색/필터링/집계에 쓰이지 않는 데이터는 제외하는 것이 성능에 유리
🧷 타입 명확히 지정
데이터 예시 | 적절한 타입 |
---|---|
날짜 | date |
정수 | integer |
가격 | float |
이메일, URL | keyword |
본문, 설명, 제목 | text |
🚫 동적 매핑(auto mapping) 주의
- 설정하지 않으면 자동으로
text + keyword
로 매핑됨 → 원치 않는 분석기 적용 가능성 - 명시적인 매핑 정의 권장
2. ⚖️ text vs keyword
항목 | text | keyword |
---|---|---|
분석 여부 | 분석됨 (tokenizer, filter 적용) | 분석되지 않음 (전체값 그대로) |
검색 목적 | 전문(full-text) 검색 | 정확한 일치, 집계/정렬/필터용 |
예시 필드 | 제목, 내용, 댓글 | ID, 이메일, 태그, 카테고리 |
3. 🔀 multi-field 전략
🧠 하나의 필드를 여러 방식으로 활용
예: title
필드를 검색도 하고, 정렬/집계도 하려면?
🚨 실전 매핑 실수 모음
이 문서는 Elasticsearch를 사용할 때 자주 발생하는 매핑 설계 실수 사례들을 정리한 가이드입니다.
실수를 피하기 위한 베스트 프랙티스도 함께 소개합니다.
1. ❌ keyword 필드에 match 사용
문제 설명
keyword
필드는 분석되지 않은 문자열이기 때문에 match
쿼리로는 동작하지 않음.
"match": {
"status": "published" // keyword 필드일 경우 동작 X
}
해결 방법
match
대신term
쿼리를 사용해야 함
"term": {
"status": "published"
}
2. ❌ text 필드로 정렬
문제 설명
text
필드는 분석된 문자열이기 때문에 정렬이 불가능하거나 성능이 매우 나쁨.
🛠️ 매핑 + 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 삽입 | 대량 데이터 테스트를 위한 빠른 삽입 |