2019. 5. 25. 16:03ㆍSearch-Engine/Elasticsearch&Solr
이번에 포스팅할 내용은 More Like This 입니다. More Like This 쿼리란 주어진 질의문과 가장 유사한 문서를 찾는 알고리즘입니다. 그리고 해당 알고리즘을 사용하지 위해서는 쿼리를 날릴 필드가 인덱싱되어야하며 분석 속도를 높이기 위하여 term_vector 속성을 지정해주는 것이 좋습니다. 필자를 참고로 간단한 Q&A를 위한 챗봇을 만들기 위하여 해당 알고리즘을 이용하였습니다. 물론 문맥을 이해하는 것이 아니라 유사도를 판단하는 것이지만 나름 성능이 나오는 알고리즘입니다. 모든 예제는 이전에 이용하였던 High Level Rest Client를 이용하였습니다.
Index
한글형태소 분석기가 포함된 인덱스를 생성하는 코드입니다. 참고로 질의의 대상이 되는 "question"필드의 term_vector 속성을 "yes"로 지정하였습니다. 생성 후에 몇개 예제로 문서를 색인해주세요.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
@RequestMapping("/create")
public Object createIndex() {
boolean acknowledged = false;
try(
RestHighLevelClient client = createConnection()
){
//index name
String indexName = "sample-korean-index";
//type name
String typeName = "_doc";
//settings
XContentBuilder settingsBuilder = XContentFactory.jsonBuilder()
.startObject()
.field("number_of_shards",5)
.field("number_of_replicas",1)
.startObject("analysis")
.startObject("tokenizer")
.startObject("sample-nori-tokenizer")
.field("type","nori_tokenizer")
.field("decompound_mode","mixed")
.field("user_dictionary","user_dictionary.txt")
.endObject()
.endObject()
.startObject("analyzer")
.startObject("sample-nori-analyzer")
.field("type","custom")
.field("tokenizer","sample-nori-tokenizer")
.array("filter",new String[]{
"sample-nori-posfilter",
"nori_readingform",
"sample-synonym-filter",
"sample-stop-filter"
}
)
.endObject()
.endObject()
.startObject("filter")
.startObject("sample-nori-posfilter")
.field("type","nori_part_of_speech")
.array("stoptaags",new String[] {
"E","IC","J","MAG","MM","NA","NR","SC",
"SE","SF","SH","SL","SN","SP","SSC","SSO",
"SY","UNA","UNKNOWN","VA","VCN","VCP","VSV",
"VV","VX","XPN","XR","XSA","XSN","XSV"
}
)
.endObject()
.startObject("sample-synonym-filter")
.field("type","synonym")
.field("synonyms_path","synonymsFilter.txt")
.endObject()
.startObject("sample-stop-filter")
.field("type","stop")
.field("stopwords_path","stopFilter.txt")
.endObject()
.endObject()
.endObject()
.endObject();
//mapping info
XContentBuilder indexBuilder = XContentFactory.jsonBuilder()
.startObject()
.startObject(typeName)
.startObject("properties")
.startObject("question")
.field("type","text")
.field("analyzer","sample-nori-analyzer")
.field("term_vector","yes")
.endObject()
.startObject("answer")
.field("type","keyword")
.endObject()
.endObject()
.endObject()
.endObject();
//인덱스생성 요청 객체
CreateIndexRequest request = new CreateIndexRequest(indexName);
//세팅 정보
request.settings(settingsBuilder);
//매핑 정보
request.mapping(typeName, indexBuilder);
//별칭설정
String aliasName = "chatbotInstance";
request.alias(new Alias(aliasName));
//인덱스생성
CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
acknowledged = response.isAcknowledged();
}catch (Exception e) {
e.printStackTrace();
return "인덱스 생성에 실패하였습니다. - catch";
}
return acknowledged == true ? "인덱스가 생성되었습니다.":"인덱스생성에 실패하였습니다.";
}
|
cs |
More Like This Query
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
@RequestMapping("/mlt")
public Object mlt() {
String aliasName = "chatbotInstance";
String typeName = "_doc";
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
searchSourceBuilder.query(QueryBuilders.moreLikeThisQuery
(new String[] {"question"},new String[]{"사용자 발화 입니다. "},null)
.minTermFreq(2)
.minDocFreq(1)
);
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
searchSourceBuilder.sort(new FieldSortBuilder("answer").order(SortOrder.DESC));
SearchRequest request = new SearchRequest(aliasName);
request.types(typeName);
request.source(searchSourceBuilder);
SearchResponse response = null;
SearchHits searchHits = null;
List<Answer> resultMap = new ArrayList<>();
try(RestHighLevelClient client = createConnection();){
response = client.search(request, RequestOptions.DEFAULT);
searchHits = response.getHits();
for( SearchHit hit : searchHits) {
Map<String, Object> sourceAsMap = hit.getSourceAsMap();
Answer a = new Answer();
a.setQuestion(sourceAsMap.get("question")+"");
a.setAnswer(sourceAsMap.get("answer")+"");
resultMap.add(a);
}
}catch (Exception e) {
e.printStackTrace();
/*
* 예외처리
*/
}
return resultMap;
}
private class Answer{
private String question;
private String answer;
private String score;
public String getQuestion() {
return question;
}
public void setQuestion(String question) {
this.question = question;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
}
|
cs |
파라미터 설명
Parameters
Document Input Parameters
- like
작성된 문서 또는 text를 바탕으로 문서를 검색 합니다.
- unlike
작성된 문서 또는 text에서 제외 시킬 term을 작성 합니다.
- fields
문서에서 analyzed text 를 가져올 필드를 지정 합니다.
이 필드를 대상으로 질의 수행이 이루어 집니다.
- like_text
like 와 더불어 문서를 검색 할떄 추가적으로 사용할 text를 작성 합니다.
- ids or docs
@deprecated
Term Selection Parameters
- max_query_terms
작성된 문서 또는 text에서 추출하여 사용할 최대 query term size 입니다. (default 25)
- min_term_freq
작성된 문서 또는 text의 최소 TF 값으로 이 값보다 작을 경우 작성된 문서와 text는 무시 됩니다. (default 2)
- min_doc_freq
입력된 개별 term들에 대해서 각각 matching 된 문서의 최소 크기로 해당 크기 보다 작은 term의 결과는 무시 됩니다. (default 5)
- max_doc_freq
입력된 개별 term들에 대해서 각각 matching 된 문서의 최대 크기로 해당 크기 보다 큰 term의 결과는 무시 됩니다. (default unbounded 0)
- min_word_length
입력된 개별 term들의 최소 길이로 정의한 값보다 작은 term은 무시 됩니다. (default 0)
- max_word_length
입력된 개별 term들의 최대 길이로 정의한 값보다 큰 term은 무시 됩니다. (default unbounded 0)
- stop_words
불용어 목록을 등록 합니다.
- analyzer
입력한 문서와 text에 대한 analyzer 를 지정 합니다. 지정 하지 않을 경우 first field 의 analyzer 를 사용하게 됩니다.
Query Formation Parameters
- minimum_should_match
작성된 문서 또는 text에서 추출된 term matching 에 대한 minimum_should_match 정보를 구성 합니다. (default 30%)
- boost_terms
tems boost value 를 지정 합니다.
- include
검색 결과로 입력 문서를 포함 할지 말지를 결정 합니다. (default false)
- boost
전체 질의에 대한 boost value 를 지정 합니다. (default 1.0)
'Search-Engine > Elasticsearch&Solr' 카테고리의 다른 글
Elasticsearch - 엘라스틱서치와 루씬의 관계 - 2(세그먼트 불변성,Translog) (1) | 2019.05.25 |
---|---|
Elasticsearch - 엘라스틱서치와 루씬의 관계 - 1 (1) | 2019.05.25 |
Elasticsearch - High Level Rest Client API Doc (0) | 2019.05.25 |
Elasticsearch - 6. Elasticsearch Java Client !(엘라스틱서치 자바 클라이언트,High-Level Rest Client) (2) | 2019.05.25 |
Elasticsearch - 5. 고급 검색(검색결과 하이라이트,검색 템플릿,별칭(Alias ,백업&복구 등) (0) | 2019.05.11 |