Elasticsearch5 [๊ธฐ๋ฅ ๊ฐ์ ] ์๋ ์์ฑ + ๋ถ๋ถ ๊ฒ์, ๊ฐ์ด ์ฐ๋ฉด ์ ๋๋ ์ด์ (feat. Nori ์ ์ฉ) ๐ ํ๊ธ ํํ์ ๋ถ์๊ธฐ๋ก ๊ฒ์ ์ ํ๋ ๊ฐ์ ํ๊ธฐ: Nori + ์๋์์ฑ ๋ถ๋ฆฌ ์ ๋ต ๐ญ ๋ฌธ์ ์ธ์ ๊ธฐ์กด์๋ ์ฑ์ฉ ๊ณต๊ณ ๊ฒ์์ ๋ถ๋ถ ๊ฒ์(N-gram)๊ณผ ์๋ ์์ฑ(Edge N-gram) ๊ธฐ๋ฅ์ ํจ๊ป ์ ์ฉํ๊ณ ์์๋ค.๊ธฐ๋ณธ์ ์ธ ๊ฒ์์ ๊ฐ๋ฅํ์ง๋ง, ์ฌ์ฉ์๊ฐ ๊ธฐ๋ํ๋ ์ ํํ ๊ฒ์ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ์ง ๋ชปํ๋ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ๋ฐ์ํ๋ค. ๐ ์์์ฌ์ฉ์๊ฐ "์นด๋"๋ผ๋ ๋จ์ด๋ฅผ ํฌํจํ ์ฑ์ฉ ๊ณต๊ณ ๋ฅผ ์ฐพ๊ณ ์ถ์ ๋, ์๋ ์์ฑ ๊ธฐ๋ฅ์ด ํจ๊ป ๋์ํ๋ฉด์์นด๋ก ์์ํ๋ ์ ํ ๋ค๋ฅธ ์ฑ์ฉ ๊ณต๊ณ ๋ค๊น์ง ํจ๊ป ๊ฒ์๋๋ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.๊ฒฐ๊ณผ์ ์ผ๋ก ์ํ๋ ๊ฒฐ๊ณผ๋ณด๋ค ๋๋ฌด ๋ง์ ๋ฐ์ดํฐ๊ฐ ํจ๊ป ๋ ธ์ถ๋๋ฉด์ ์ฌ์ฉ์๋ ์ ํํ ๊ฒ์์ด ์ด๋ ต๋ค๋ ์ธ์์ ๋ฐ๊ฒ ๋์๋ค. ๐งฑ ๊ธฐ์กด ์ธ๋ฑ์ค ๊ตฌ์กฐ์ ํ๊ณ ๊ธฐ์กด ์ธ๋ฑ์ค ์ค์ ์์๋ title, requiredSkills.. 2025. 4. 3. [๊ธฐ๋ฅ ๊ฐ์ ] ์ฑ์ฉ ๊ณต๊ณ ๊ฒ์ ์๋ 48ms → 14ms, ์ด๋ป๊ฒ ๊ฐ๋ฅํ์๊น? ๐ QueryDSL์์ Elasticsearch๋ก, ์ฑ์ฉ ๊ณต๊ณ ์กฐํ ์ฑ๋ฅ ๊ฐ์ ๐ญ ๋ฌธ์ ์ธ์ ์ฒ์์๋ MySQL + QueryDSL ๊ธฐ๋ฐ์ผ๋ก ์ฑ์ฉ ๊ณต๊ณ ๋ฅผ ์กฐํํ๊ณ ์์๋ค.๋จ์ ์กฐํ ์ฑ๋ฅ ์์ฒด๋ ๋น๊ต์ ๋น ๋ฅธ ํธ์ด์๋ค.ํ์ง๋ง ์๋น์ค๊ฐ ์ฑ์ฅํ๋ฉด์ ๋ถ๋ถ ๊ฒ์์ด๋ ์๋ ์์ฑ ๋ฑ ๊ฒ์ ํธ์ ๊ธฐ๋ฅ์ ํ์ฅํด์ผ ํ ํ์์ฑ์ด ์ปค์ก๊ณ , ์ด๋ฅผ QueryDSL๋ง์ผ๋ก ๊ตฌํํ๊ธฐ์ ๊ตฌ์กฐ์ ํ๊ณ๊ฐ ์์๋ค.ํนํ ์ ์ฒด ์ฑ์ฉ ๊ณต๊ณ ๋ฅผ ๋์์ผ๋ก ํค์๋ ๊ธฐ๋ฐ ๊ฒ์์ด๋ ์ฌ์ฉ์ ์ ๋ ฅ์ ์ค์๊ฐ์ผ๋ก ๋ฐ์ํ๋ ๊ธฐ๋ฅ์ Elastisearch๊ฐ ๋ ์ ํฉํ ๊ธฐ์ ์ด๋ผ๊ณ ํ๋จํ๋ค. ๐ Elasticsearch ๋์ ๋ฐฐ๊ฒฝ์ฑ์ฉ ๊ณต๊ณ ๊ฒ์ ๊ธฐ๋ฅ์ ๋จ์ ํค์๋ ์กฐํ์ ๊ทธ์น์ง ์๊ณ ๋ถ๋ถ ๊ฒ์, ์๋ ์์ฑ ๋ฑ ๊ฒ์ ํธ์ ๊ธฐ๋ฅ์ ํ์ฅํ ํ์๊ฐ ์์๋ค.ํ์ง๋ง MyS.. 2025. 4. 3. [ํธ๋ฌ๋ธ์ํ ] @Setting์ ์ผ๋๋ฐ ์ ์ธ๋ฑ์ค๊ฐ ์ ๋ ๊น? ๐งจ Elasticsearch ์ธ๋ฑ์ค ์ค์ ์ด ์ ๋๋ค?! @Setting ์คํจ ๊ธฐ๋ก ๐ฅ๋ฌธ์ ์ํฉSpring Boot + Spring Data Elasticsearch ํ๊ฒฝ์์Elasticsearch์์ ๊ฒ์ ์ฑ๋ฅ ๊ฐ์ ์ ์ํด n-gram, edge-ngram ๊ธฐ๋ฐ ์ธ๋ฑ์ค ์ค์ ์ ์ ์ฉํ๋ ค๊ณ ํ๋ค.์๋์ ๊ฐ์ด job-opening-settings.json์ ์์ฑํ๊ณ ,Spring Data Elasticsearch์ @Setting ์ด๋ ธํ ์ด์ ์ ํตํด ์๋์ผ๋ก ์ธ๋ฑ์ค๋ฅผ ์์ฑํ๋ ค๊ณ ํ๋ค.๋๋ณด๊ธฐ job-opening-settings.json { "settings": { "analysis": { "filter": { "ngram_filter": { "type": "ng.. 2025. 4. 2. [ ํธ๋ฌ๋ธ ์ํ ] Elasticsearch ์ธ๋ฑ์ค ์ฝ์ ๋ฐ ์กฐํ ์คํจ ๋ฌธ์ ํด๊ฒฐ๊ธฐ (์ธ๋ฑ์ค, ๋งคํ, ID ์ค๋ณต) Elasticsearch ๋ฐ์ดํฐ ์ฝ์ ๋ฐ ์กฐํ ๋ฌธ์ ํด๊ฒฐ ๊ณผ์ Elasticsearch์ CSV ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ํ๊ณ ์กฐํํ๋ ๊ณผ์ ์์ ๋ฐ์ดํฐ๊ฐ ์กฐํ๋์ง ์์ ์์ธ์ ๋ถ์ํ๊ณ ํด๊ฒฐํ๋ ๊ณผ์ ์ ์ ๋ฆฌํด ๋ดค๋ค.๋ฐ์ํ ๋ฌธ์ ์ ์์ธ ๋ถ์1. ์ธ๋ฑ์ค ๋ค์ด๋ฐ ๋ถ์ผ์น ๋ฌธ์ ๋ฌธ์ ์ํฉElasticsearch์์ ์ธ๋ฑ์ค๋ฅผ ์์ฑํ ๋๋ "job-opening"์ผ๋ก ์ค์ ํ์ง๋ง, ๋ฐ์ดํฐ๋ฅผ ์กฐํํ ๋๋ "job_opening"์ผ๋ก ์กฐํํ๋ ์ค์๋ฅผ ๋ฒํ๋ค.Kibana์์ ์กฐํ ์ ๋ฐ์ดํฐ๊ฐ ๋ํ๋์ง ์์๋ค.ํด๊ฒฐ ๋ฐฉ๋ฒ ์ธ๋ฑ์ค๋ช ์ ์์(static final)๋ก ์ ์ํ์ฌ, ์์ฑ๊ณผ ์กฐํ ์ ์ผ๊ด์ฑ์ ์ ์งํ๋ค.public static final String INDEX_NAME = "job-opening"; 2. ๋์ ๋งคํ(@Postconstr.. 2025. 2. 25. [ ํธ๋ฌ๋ธ ์ํ ] Elasticsearch keyword ํ๋์ ์ค์์ฑ (term ์ฟผ๋ฆฌ๊ฐ ์๋ ๋) Elasticsearch์์ term ์ฟผ๋ฆฌ๊ฐ ๋์ํ์ง ์๋ ๋ฌธ์ ํด๊ฒฐ ๋ฌธ์ ์ํฉ์ฑ์ฉ ๊ณต๊ณ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ์ Spring API์ Elasticsearch๋ฅผ ์ฐ๋ํ์ฌ ๊ตฌํํ๋ ์ค, ์๊ฒฉ ์๊ฑด(requiredSkills)์ term ์ฟผ๋ฆฌ๋ฅผ ํตํด ํํฐ๋งํ๋๋ ๋ฐ์ดํฐ๊ฐ ์ ํ ์กฐํ๋์ง ์๋ ํ์์ด ๋ฐ์ํ๋ค.๊ธฐ์กด ์ฟผ๋ฆฌ// ์๊ฒฉ ์๊ฑด ํํฐ๋งif (requestDto.getRequiredSkill() != null) { boolQueryBuilder.filter(f -> f .term(t -> t .field("requiredSkills") .value(requestDto.getRequiredSkill()) ) );}์์ธ ๋ถ์๋จผ์ Ela.. 2025. 2. 25. ์ด์ 1 ๋ค์