Spring Boot : 사용자 검색 API, 관리자 데이터 추가 API
Elasticsearch : 역색인 바탕 데이터 검색 엔진 & NoSQL
MySQL : 트랜잭션 보장용 데이터 영속 보관소 & 데이터 관리
Spring Batch : 대규모 MySQL 데이터 ES 이관 배치 처리
JavaScript : 검색 데이터 페이징 처리 결과 반환
Python : xls 원본 데이터 csv 컨버팅
단어(entry) 우선, 설명(definition) 검색 데이터 일치 추천 연산 정렬
검색어 일치 하이라이팅, 페이지네이션 반환
MySQL 사전 저장된 75000개 가량 데이터 ES 배치 이관, 이벤트 기반 실시간 동기화
Kafka 같은 메세지 큐 도입으로 대용량 이벤트 동기화 처리
초성 검색, 자동완성 등 ES 기능 추가 공부 필요
// index 초기화, PUT /koreans
{
"settings" : {
"index" : { "max_ngram_diff" : 30 },
"analysis" : {
"analyzer" : {
"my_custom_analyzer" : {
"type" : " custom" , "char_filter" : [],
"tokenizer" : " my_nori_tokenizer" ,
"filter" : [" lowercase_filter" , " synonym_filter" ]
},
"autocomplete_analyzer" : {
"type" : " custom" , "tokenizer" : " autocomplete_tokenizer" , "filter" : [" lowercase" ]
},
"ngram_analyzer" : {
"type" : " custom" , "tokenizer" : " ngram_tokenizer" , "filter" : [" lowercase" ]
},
"chosung_analyzer" : { // 나중에 추가하기
"type" : " custom" , "tokenizer" : " standard" , "filter" : [" lowercase" ]
}
},
"tokenizer" : {
"my_nori_tokenizer" : {
"type" : " nori_tokenizer" , "decompound_mode" : " mixed" , "discard_punctuation" : " true" ,
"user_dictionary" : " dict/userdict_ko.txt" , "lenient" : true
},
"autocomplete_tokenizer" : {
"type" : " edge_ngram" , "min_gram" : 2 , "max_gram" : 30 , "token_chars" : [" letter" , " digit" ]
},
"ngram_tokenizer" : {
"type" : " ngram" , "min_gram" : 2 , "max_gram" : 30 , "token_chars" : [" letter" , " digit" ]
}
},
"filter" : {
"lowercase_filter" : { "type" : " lowercase" },
"synonym_filter" : {
"type" : " synonym" , "synonyms_path" : " dict/synonym-set.txt" , "lenient" : true
}
},
"normalizer" : {
"chosung_normalizer" : { "type" : " custom" , "filter" : [" lowercase" ] }
}
}
},
"mappings" : {
"properties" : {
"entry" : {
"type" : " text" , "analyzer" : " my_custom_analyzer" ,
"fields" : {
"autocomplete" : { "type" : " text" , "analyzer" : " autocomplete_analyzer" },
"ngram" : { "type" : " text" , "analyzer" : " ngram_analyzer" },
"chosung" : { "type" : " keyword" , "normalizer" : " chosung_normalizer" } // 나중에 추가하기
}
},
"type" : { "type" : " keyword" },
"pos" : { "type" : " keyword" },
"definition" : {
"type" : " text" , "analyzer" : " my_custom_analyzer" ,
"fields" : {
"ngram" : { "type" : " text" , "analyzer" : " ngram_analyzer" }
}
},
"entry_chosung" : {
"type" : " keyword" , "normalizer" : " chosung_normalizer" ,
"fields" : {
"autocomplete" : { "type" : " text" , "analyzer" : " autocomplete_analyzer" },
"ngram" : { "type" : " text" , "analyzer" : " ngram_analyzer" }
}
}
}
}
}
// search 예시, GET /koreans/_search
{
"size" : 10 ,
"query" : {
"dis_max" : {
"queries" : [
{ "match" : { "entry" : { "query" : " 검색" , "boost" : 2 }}},
{ "match" : { "entry.ngram" : { "query" : " 검색" , "boost" : 1 }}},
{ "match" : { "entry.autocomplete" : { "query" : " 검색" , "boost" : 0.2 }}}
]
}
},
"highlight" : {
"fields" : {
"entry" : {
"pre_tags" : [" <strong>" ],
"post_tags" : [" </strong>" ]
},
"definition" : {
"pre_tags" : [" <strong>" ],
"post_tags" : [" </strong>" ]
}
}
}
}
향후 초성 기반 검색, 영문 포함 검색 확장하여 재인덱싱 예정
WAS의 ElasticsearchClient 통해 추천 점수 바탕 정렬
2) 관리자 MySQL CRUD 실시간 ES 동기화
@ Slf4j
@ Component
@ RequiredArgsConstructor
public class TransactionalKoreanEventListener implements KoreanEventListener {
private final ElasticsearchClient elasticsearchClient ;
@ Override
@ TransactionalEventListener (phase = TransactionPhase .AFTER_COMMIT )
public void listenCreateEvent (CreateEvent event ) throws IOException {
log .info ("생성 이벤트 발생, {}" , event .getId ());
elasticsearchClient .index (i -> i .index ("koreans" )
.id (String .valueOf (event .getId ()))
.document (event .getDto ()));
}
@ Override
@ TransactionalEventListener (phase = TransactionPhase .AFTER_COMMIT )
public void listenUpdateEvent (UpdateEvent event ) throws IOException {
log .info ("전체 업데이트 이벤트 발생, {}" , event .getId ());
elasticsearchClient .update (u -> u .index ("koreans" )
.id (String .valueOf (event .getId ()))
.doc (event .getDto ())
.docAsUpsert (true )
, KoreanUpdateDTO .class );
}
// ...
ApplicationEventPulisher 의존성 주입
커스텀 이벤트 객체 리스너 등록