[κΈ°λ₯ κ°μ ] μλ μμ± + λΆλΆ κ²μ, κ°μ΄ μ°λ©΄ μ λλ μ΄μ (feat. Nori μ μ©)
π νκΈ ννμ λΆμκΈ°λ‘ κ²μ μ νλ κ°μ νκΈ°: Nori + μλμμ± λΆλ¦¬ μ λ΅
π λ¬Έμ μΈμ
κΈ°μ‘΄μλ μ±μ© κ³΅κ³ κ²μμ λΆλΆ κ²μ(N-gram)κ³Ό μλ μμ±(Edge N-gram) κΈ°λ₯μ ν¨κ» μ μ©νκ³ μμλ€.
κΈ°λ³Έμ μΈ κ²μμ κ°λ₯νμ§λ§, μ¬μ©μκ° κΈ°λνλ μ νν κ²μ κ²°κ³Όλ₯Ό λ°ννμ§ λͺ»νλ κ²½μ°κ° μ’
μ’
λ°μνλ€.
π μμ
μ¬μ©μκ° "μΉ΄λ"λΌλ λ¨μ΄λ₯Ό ν¬ν¨ν μ±μ© κ³΅κ³ λ₯Ό μ°Ύκ³ μΆμ λ, μλ μμ± κΈ°λ₯μ΄ ν¨κ» λμνλ©΄μ
μΉ΄λ‘ μμνλ μ ν λ€λ₯Έ μ±μ© κ³΅κ³ λ€κΉμ§ ν¨κ» κ²μλλ λ¬Έμ κ° λ°μνλ€.
κ²°κ³Όμ μΌλ‘ μνλ κ²°κ³Όλ³΄λ€ λ무 λ§μ λ°μ΄ν°κ° ν¨κ» λ ΈμΆλλ©΄μ μ¬μ©μλ μ νν κ²μμ΄ μ΄λ ΅λ€λ μΈμμ λ°κ² λμλ€.
π§± κΈ°μ‘΄ μΈλ±μ€ ꡬ쑰μ νκ³
κΈ°μ‘΄ μΈλ±μ€ μ€μ μμλ title, requiredSkills λ±μ νλμ λ€μ λ λΆμκΈ°λ₯Ό ν¨κ» μ μ©νκ³ μμλ€.
β
ngram_analyzer → λΆλΆ κ²μμ©
β
autocomplete_analyzer → μλ μμ±μ©
"title": {
"type": "text",
"fields": {
"ngram": { "type": "text", "analyzer": "ngram_analyzer" },
"autocomplete": { "type": "text", "analyzer": "autocomplete_analyzer" }
}
}
π μ΄ κ΅¬μ‘°λ λ¨μ΄μ μΌλΆλΆλ§ μ λ ₯ν΄λ κ²μμ΄ κ°λ₯νλ€λ μ₯μ μ΄ μμμ§λ§, λ¬Έμ λ λ κΈ°λ₯μ΄ κ°μ κ²μ APIμμ λμμ μλνλ©΄μ κ²μ κ²°κ³Όμ μ λ°λκ° ν¬κ² λ¨μ΄μ§λ νμμ΄ λ°μνλ€λ μ μ΄λ€.
μ¬μ©μκ° μ ννκ² νΉμ ν€μλλ₯Ό κ²μνλλΌλ μλ μμ±μ© ν ν°μ΄ ν¨κ» μ‘°νλλ©° μνμ§ μλ λ°μ΄ν°κ° κ³Όλνκ² ν¬ν¨λλ λ¬Έμ λ‘ μ΄μ΄μ‘λ€.
π§ ν΄κ²° λ°©ν₯: Nori ννμ λΆμκΈ° + κΈ°λ₯ λΆλ¦¬
νκ΅μ΄λ μμ΄μ λ¬λ¦¬ μ‘°μ¬, μ΄λ―Έ, 볡ν©μ΄ λ± κ΅¬μ± λ°©μμ΄ λ³΅μ‘νκΈ° λλ¬Έμ
λ¨μν N-gram λΆμκΈ°λ§μΌλ‘λ μ νν μλ―Έ λ¨μ λΆμμ νκ³κ° μλ€.
κ·Έλμ, λ€μκ³Ό κ°μ κ°μ λ°©ν₯μ μ€μ νλ€.
β
Nori ννμ λΆμκΈ°λ₯Ό λμ
π νκ΅μ΄λ₯Ό ννμ λ¨μλ‘ λΆμνμ¬ λ³΄λ€ μλ―Έ μ€μ¬μ κ²μμ΄ κ°λ₯νλλ‘ κ°μ
π "κ°λ°μκ°" → [κ°λ°, μ]
π μ‘°μ¬/μ΄λ―Έ μ κ±° + μ¬μ©μ μ¬μ λ±λ‘λ κ°λ₯
β
μλ μμ± κΈ°λ₯μ λ³λμ APIλ‘ λΆλ¦¬
π κ²μ μ λ°λμ μν₯μ μ£Όμ§ μλλ‘ κΈ°λ₯μ μ±
μμ λΆλ¦¬
π μ νν ν€μλ κ²μκ³Ό νΌλλμ§ μκ² μ€κ³
π§ͺ Nori λΆμκΈ° μ μ©
Elasticsearchμμλ νκ΅μ΄ ννμ λΆμμ μν΄ Nori λΆμκΈ°μ Nori Tokenizerλ₯Ό μ 곡νλ€.
νλͺ© | Nori λΆμκΈ° | Nori Tokenizer |
μν | νκΈ ν μ€νΈλ₯Ό ννμλ‘ λΆλ¦¬νλ μμ±ν Analyzer | ννμ λ¨μλ‘ Tokenizingλ§ μν |
μμ | λ°±μλ κ°λ°μ → [λ°±μλ, κ°λ°, μ] |
μλ° κ°λ°μ → [μλ°, κ°λ°, μ] |
π μ‘°μ¬ λ° μ΄λ―Έ μ κ±°, μ¬μ©μ μ¬μ μ€μ , 볡ν©μ΄ μ²λ¦¬ λ± λ€μν νκΈ μ²λ¦¬ κΈ°λ₯ μ 곡
βοΈ λ³κ²½λ μΈλ±μ€ ꡬ쑰
"title": {
"type": "text",
"fields": {
"morph": {
"type": "text",
"analyzer": "nori_analyzer"
},
"autocomplete": {
"type": "text",
"analyzer": "autocomplete_analyzer"
}
}
}
π νλ μ€λͺ
β
morph
π μ νν κ²μμ μν Nori ννμ κΈ°λ° λΆμ μ μ©
π μ¬μ©μκ° μ
λ ₯ν ν€μλλ₯Ό μλ―Έ λ¨μλ‘ ν΄μνμ¬ μ λ°ν κ²μ κ°λ₯
β
autocomplete
π μλ μμ±μ μν Edge-Ngram λΆμκΈ° μ μ©
π μ
λ ₯κ°μ μλΆλΆμ κΈ°μ€μΌλ‘ μλ μμ± κ²μ μ 곡
π μ΄ μ€μ μΌλ‘ νκΈ ν μ€νΈλ μλ―Έ λ¨μλ‘ μ ννκ² κ²μν μ μκ³ , μλ μμ± κΈ°λ₯μ λ³λ APIλ‘ λΆλ¦¬λμ΄ κ²μ κ²°κ³Όμ μν₯μ μ£Όμ§ μλλ‘ λΆλ¦¬ μ€κ³λμλ€.
π μλμμ± κΈ°λ₯ λΆλ¦¬ λ° κ°μ
μλμμ± κΈ°λ₯μ Edge N-gram νν°λ₯Ό νμ©νμ¬ μ λ ₯ν λ¨μ΄μ μλΆλΆλ§μΌλ‘λ κ²μμ΄ κ°λ₯νκ² κ΅¬ννλ€.
"filter": {
"edge_ngram_filter": {
"type": "edge_ngram",
"min_gram": 1,
"max_gram": 25
}
}
π μμ
"νλ‘ νΈμλ κ°λ°μ" → ["ν", "νλ‘ ", "νλ‘ νΈ", "νλ‘ νΈμ", "νλ‘ νΈμλ"] λ‘ λΆν΄
β
μ¬μ©μκ° "νλ‘ "λ§ μ
λ ₯ν΄λ "νλ‘ νΈμλ κ°λ°μ"κ° ν¬ν¨λ μ±μ© κ³΅κ³ κ° μλμΌλ‘ μΆμ²λλ€!
βοΈ κΈ°λ₯ λΆλ¦¬λ‘ μ νλ ν보
μ΄μ μλ μλ μμ± νλκ° μΌλ° κ²μκ³Ό ν¨κ» λμνλ©΄μ μνμ§ μλ κ²°κ³Όκ° ν¨κ» μ‘°νλλ λ¬Έμ κ° μμλ€.
μ΄λ² κ°μ μμλ μλ μμ± κΈ°λ₯μ λ³λμ APIλ‘ λΆλ¦¬νμ¬ μ νν ν€μλ κ²μ κ²°κ³Όμ νΌν©λμ§ μλλ‘ μ²λ¦¬νλ€.
β κ²°κ³Ό λ° νμΈ
π κ°μ μ μ© ν, κΈ°λ₯μ κ°κ°μ λͺ©μ μ λ§κ² λͺ ννκ² λΆλ¦¬λμ΄ λμνλ€.
π μΌλ° κ²μ (Nori λΆμκΈ° μ μ©)
π "μΉ΄λ" ν€μλλ‘ κ²μ μ μ νν "μΉ΄λ"λ₯Ό ν¬ν¨νλ μ±μ© κ³΅κ³ λ§ μ‘°ν
β¨ μλμμ± (Edge-Ngram)
π "μΉ΄"λ§ μ
λ ₯ν΄λ "μΉ΄λ", "μΉ΄μΉ΄μ€" λ± κ΄λ ¨ κ²°κ³Όλ₯Ό μ 곡
μ΄μ λ κ²μκ³Ό μλ μμ±μ΄ μλ‘ λ°©ν΄νμ§ μκ³ , κ°μμ μν μ μΆ©μ€νκ² λμνλ€!
β νκ³
μ΄λ² μμ μ ν΅ν΄ νκΈ κ²μ νκ²½μμλ μ νλμ μ¬μ©μ κ²½νμ λͺ¨λ κ³ λ €ν κ²μ ꡬ쑰λ₯Ό μ€κ³νκ³ κ΅¬νν μ μμλ€.
π‘ ν΅μ¬ μ 리
β
ννμ λΆμ(Nori) + μλμμ±(Edge-Ngram)
β
κ²μ λͺ©μ λ³ νλ λΆλ¦¬ + κΈ°λ₯ API λΆλ¦¬
μ΄λ² κ²½νμ ν΅ν΄ Elasticsearchμ μ μ°ν μΈλ±μ€ μ€κ³μ νμ₯μ± λμ κ²μ κΈ°λ₯μ μ§μ λ€λ€λ³΄λ©΄μ μ€μ κ°κ°λ ν€μΈ μ μμλ€.
μμΌλ‘λ λ€μν ν
μ€νΈ κΈ°λ° κΈ°λ₯μμ μΈμ΄ νΉμ±κ³Ό κ²μ λͺ©μ μ λ§λ ꡬ쑰 μ€κ³κ° μΌλ§λ μ€μνμ§ λ κΉμ΄ κ³ λ―Όνκ² λ κ² κ°λ€.