Repository navigation
[Feat] 약 검색 품질 재설계 (초성·edge n-gram·오타·관련도) #92
Copy link
Copy link
Closed
Labels
✨ Feature기능 개발기능 개발
Description
📌 Description
현재 약 검색(GET /api/search/drugs)은 DrugDocument.itemName에 기본(standard) 애널라이저 + match_phrase_prefix 쿼리 하나만 사용한다. 다음 한계가 있다.
- 한글 형태소 분석 없음 → "타이레놀 500" vs "타이레놀500" 토큰화 불일치
- 초성 검색 불가 (
ㅌㅇㄹㄴ→ 0건) - 오타 불가 (
타이레올→ 0건) match_phrase_prefix는 마지막 토큰만 prefix 취급 + 스코어링이 빈약 → 결과 순서가 사실상 무작위- 제품명 중간 단어로 검색 불가 ("이알서방")
전제
무중단 재색인 인프라(#90, alias + POST /api/admin/drugs/reindex)가 머지되어, DrugDocument 매핑을 바꾼 뒤 재색인 API 한 번으로 다운타임 없이 반영할 수 있다. 이 이슈는 그 매핑/쿼리를 실제로 고도화한다.
🎯 목표
| 지표 | 현재(측정 필요) | 목표 |
|---|---|---|
| 검색 p95 latency | ? | 현재 수준 유지 |
| 정답률 (라벨링 20~30개, Recall@10) | ? | ≥ 0.9 |
| 초성 검색 | ❌ | ✅ (ㅌㅇㄹㄴ → 타이레놀 계열) |
| 오타 1글자 허용 | ❌ | ✅ (타이레올 → 타이레놀 계열) |
| 관련도 정렬 | ❌ | ✅ (완전일치 > 시작일치 > 부분일치) |
🛠️ 작업 범위
1. 인덱스 settings/mappings 재설계 (DrugDocument)
itemName을 멀티필드로:
itemName— nori 형태소 분석 (정확 매칭용)itemName.ngram—edge_ngram(min 1, max 20) 자동완성용itemName.chosung— 초성 필드 (색인 시 Java에서 자모 분해 후 주입)number_of_replicas: 0명시 (single-node → 현재 클러스터 yellow)
@Setting으로 커스텀 애널라이저 정의. DrugIndexManager.createTimestampedIndex()가 createSettings()/createMapping()으로 그대로 반영하므로 코드 변경 없이 재색인 API로 배포된다.
2. 초성 분해 유틸 (HangulChosungExtractor)
- "타이레놀정" → "ㅌㅇㄹㄴㅈ"
- 한글 유니코드 조합 분해 (0xAC00 기준 초성 인덱스)
- 비한글(숫자/영문)은 그대로 통과
DrugInfoConverter.toDocument에서chosung필드 채움
3. 검색 쿼리 교체 (DrugSearchRepository / DrugSearchQueryService)
match_phrase_prefix → bool.should 조합:
match itemName.ngram(자동완성 기본, boost 1)match itemName+fuzziness: AUTO(정확 일치 + 오타, boost 3)term itemName.chosung(입력이 전부 초성일 때만, boost 2)
입력이 "전부 초성인지" 판별해 chosung 절 on/off.
4. 관련도 정렬
function_score또는boolboost로 완전일치 > 시작일치 > 부분일치DrugSearchQueryService.search가SearchHit<DrugDocument>를 받도록 변경 →_score보존 (현재는 버려짐)- (선택)
DrugSearchResponse에 score 필드 — 튜닝/디버깅용, 최종 노출 여부는 논의
5. (선택) 동의어
- 성분명(아세트아미노펜) ↔ 대표 제품명 매핑 사전
- 범위 크면 별도 이슈로 분리
6. before/after 측정
- 라벨링 테스트셋(약명 20~30개 + 기대 결과) → Recall@10, MRR
- p95 latency
- 재색인 중 1초 간격 검색 → 실패 요청 0건 로그 (무중단 검증)
✅ To-do
- 인덱스 settings/mappings JSON 정의 (nori + edge_ngram + chosung analyzer, replicas 0)
-
HangulChosungExtractor+ 단위 테스트 (혼합 문자열, 자음/모음만, 빈 문자열) -
DrugDocument멀티필드 +@Setting반영 -
DrugInfoConverter.toDocument— chosung 주입 -
DrugSearchRepository쿼리 교체 -
DrugSearchQueryService— 초성 입력 판별,SearchHit수신, score 처리 - [Feat] DrugInfo ES 무중단 재색인 인프라 (alias + reindex API) #90 재색인 API로 신규 매핑 반영 (수동 검증)
- 검색 품질 테스트셋 + before/after 측정 스크립트
📒 기타
- nori 플러그인: ES 8.x 기본 번들에
analysis-nori포함 (별도 설치 불필요) — 확인 - 폴백(MySQL LIKE,
/api/drugs/search)은 이번 범위 아님 — 그대로 둠 - 커밋 분리: util(chosung) → document → converter → repository → service
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
✨ Feature기능 개발기능 개발
Activity