6.6.3 Synonym
이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민([email protected])에게 사용 내용을 알려주시기 바랍니다.
검색 서비스에 따라서 동의어 검색을 제공해야 하는 경우가 있습니다. 예를 들면 클라우드 서비스 관련 정보를 검색하는 시스템에서 "AWS" 라는 단어를 검색했을 때 "Amazon" 또는 한글 "아마존" 도 같이 검색을 하도록 하면 관련된 정보를 더 많이 찾을 수 있을 것입니다. 이 때 Synonym 토큰 필터를 사용하면 텀의 동의어 저장이 가능합니다.
동의어를 설정하는 옵션은 synonyms 항목에서 직접 동의어 목록을 입력하는 방법과 동의어 사전 파일을 만들어 synonyms_path 로 지정하는 방법이 있습니다. 동의어 사전 명시 규칙에는 다음의 것들이 있습니다.
  • "A, B => C" : 왼쪽의 A, B 대신 오른쪽의 C 텀을 저장합니다. A, B 로는 C 의 검색이 가능하지만 C 로는 A, B 가 검색되지 않습니다.
  • "A, B" : A, B 각 텀이 A 와 B 두개의 텀을 모두 저장합니다. A 와 B 모두 서로의 검색어로 검색이 됩니다.
다음은 my_synonym 인덱스에 "amazon => aws" 으로 동의어를 지정하는 예제입니다.
"amazon => aws" 동의어를 지정하는 my_synonym 인덱스 생성
1
PUT my_synonym
2
{
3
"settings": {
4
"analysis": {
5
"analyzer": {
6
"my_syn": {
7
"tokenizer": "whitespace",
8
"filter": [
9
"lowercase",
10
"syn_aws"
11
]
12
}
13
},
14
"filter": {
15
"syn_aws": {
16
"type": "synonym",
17
"synonyms": [
18
"amazon => aws"
19
]
20
}
21
}
22
}
23
},
24
"mappings": {
25
"properties": {
26
"message": {
27
"type": "text",
28
"analyzer": "my_syn"
29
}
30
}
31
}
32
}
Copied!
이제 여기에 "Amazon Web Service", "AWS" 값을 가진 도큐먼트 두 개를 저장하고 각 도큐먼트의 _termvectors 를 확인 해 보겠습니다.
AWS, Amazon Web Service 도큐먼트 저장
1
PUT my_synonym/_doc/1
2
{ "message" : "Amazon Web Service" }
3
PUT my_synonym/_doc/2
4
{ "message" : "AWS" }
Copied!
request
response
1 도큐먼트 message 필드의 termvectors 확인
1
GET my_synonym/_termvectors/1?fields=message
Copied!
1 도큐먼트 message 필드의 termvectors 확인 결과
1
{
2
"_index" : "my_synonym",
3
"_type" : "_doc",
4
"_id" : "1",
5
"_version" : 1,
6
"found" : true,
7
"took" : 9,
8
"term_vectors" : {
9
"message" : {
10
"field_statistics" : {
11
"sum_doc_freq" : 4,
12
"doc_count" : 2,
13
"sum_ttf" : 4
14
},
15
"terms" : {
16
"aws" : {
17
"term_freq" : 1,
18
"tokens" : [
19
{
20
"position" : 0,
21
"start_offset" : 0,
22
"end_offset" : 6
23
}
24
]
25
},
26
"service" : {
27
"term_freq" : 1,
28
"tokens" : [
29
{
30
"position" : 2,
31
"start_offset" : 11,
32
"end_offset" : 18
33
}
34
]
35
},
36
"web" : {
37
"term_freq" : 1,
38
"tokens" : [
39
{
40
"position" : 1,
41
"start_offset" : 7,
42
"end_offset" : 10
43
}
44
]
45
}
46
}
47
}
48
}
49
}
Copied!
request
response
2 도큐먼트 message 필드의 termvectors 확인
1
GET my_synonym/_termvectors/2?fields=message
Copied!
2 도큐먼트 message 필드의 termvectors 확인 결과
1
{
2
"_index" : "my_synonym",
3
"_type" : "_doc",
4
"_id" : "2",
5
"_version" : 1,
6
"found" : true,
7
"took" : 0,
8
"term_vectors" : {
9
"message" : {
10
"field_statistics" : {
11
"sum_doc_freq" : 4,
12
"doc_count" : 2,
13
"sum_ttf" : 4
14
},
15
"terms" : {
16
"aws" : {
17
"term_freq" : 1,
18
"tokens" : [
19
{
20
"position" : 0,
21
"start_offset" : 0,
22
"end_offset" : 3
23
}
24
]
25
}
26
}
27
}
28
}
29
}
Copied!
1 도큐먼트의 "Amazon Web Service"amazon 대신 "aws", "web", "service" 로 저장된 것을 확인할 수 있습니다. 다음은 각각 term 쿼리로 aws, amazon 을 검색한 결과와 match 쿼리로 amazon 을 검색한 결과입니다.
request
response
term 쿼리로 aws 검색
1
GET my_synonym/_search
2
{
3
"query": {
4
"term": {
5
"message": "aws"
6
}
7
}
8
}
Copied!
term 쿼리로 aws 검색 결과
1
{
2
"took" : 2,
3
"timed_out" : false,
4
"_shards" : {
5
"total" : 1,
6
"successful" : 1,
7
"skipped" : 0,
8
"failed" : 0
9
},
10
"hits" : {
11
"total" : {
12
"value" : 2,
13
"relation" : "eq"
14
},
15
"max_score" : 0.22920427,
16
"hits" : [
17
{
18
"_index" : "my_synonym",
19
"_type" : "_doc",
20
"_id" : "2",
21
"_score" : 0.22920427,
22
"_source" : {
23
"message" : "AWS"
24
}
25
},
26
{
27
"_index" : "my_synonym",
28
"_type" : "_doc",
29
"_id" : "1",
30
"_score" : 0.1513613,
31
"_source" : {
32
"message" : "Amazon Web Service"
33
}
34
}
35
]
36
}
37
}
Copied!
request
response
term 쿼리로 amazon 검색
1
GET my_synonym/_search
2
{
3
"query": {
4
"term": {
5
"message": "amazon"
6
}
7
}
8
}
Copied!
term 쿼리로 amazon 검색 결과
1
{
2
"took" : 1,
3
"timed_out" : false,
4
"_shards" : {
5
"total" : 1,
6
"successful" : 1,
7
"skipped" : 0,
8
"failed" : 0
9
},
10
"hits" : {
11
"total" : {
12
"value" : 0,
13
"relation" : "eq"
14
},
15
"max_score" : null,
16
"hits" : [ ]
17
}
18
}
Copied!
request
response
match 쿼리로 amazon 검색
1
GET GET my_synonym/_search
2
{
3
"query": {
4
"match": {
5
"message": "amazon"
6
}
7
}
8
}
Copied!
match 쿼리로 amazon 검색 결과
1
{
2
"took" : 1,
3
"timed_out" : false,
4
"_shards" : {
5
"total" : 1,
6
"successful" : 1,
7
"skipped" : 0,
8
"failed" : 0
9
},
10
"hits" : {
11
"total" : {
12
"value" : 2,
13
"relation" : "eq"
14
},
15
"max_score" : 0.22920427,
16
"hits" : [
17
{
18
"_index" : "my_synonym",
19
"_type" : "_doc",
20
"_id" : "2",
21
"_score" : 0.22920427,
22
"_source" : {
23
"message" : "AWS"
24
}
25
},
26
{
27
"_index" : "my_synonym",
28
"_type" : "_doc",
29
"_id" : "1",
30
"_score" : 0.1513613,
31
"_source" : {
32
"message" : "Amazon Web Service"
33
}
34
}
35
]
36
}
37
}
Copied!
첫 번째 쿼리와 마지막 세 번째 쿼리의 결과가 동일합니다.
term 쿼리는 검색어에 애널라이저를 적용하지 않고 그대로 검색하기 때문에 term 쿼리로 aws 를 검색하면 두개의 도큐먼트가 모두 검색되고 amazon을 검색 하면 검색이 되지 않습니다. match 쿼리는 검색어 amazonmy_syn 애널라이저가 적용이 되어 aws 로 변환하여 검색을 하기 때문에 aws로 검색을 한 것과 같은 결과가 나타납니다.
이번에는 my_synonym 인덱스에 "amazon, aws" 로 동의어를 지정하는 예제입니다. 기존의 my_synonym 인덱스를 먼저 삭제하고 입력합니다.
"amazon, aws" 동의어를 지정하는 my_synonym 인덱스 생성
1
PUT my_synonym
2
{
3
"settings": {
4
"analysis": {
5
"analyzer": {
6
"my_syn": {
7
"tokenizer": "whitespace",
8
"filter": [
9
"lowercase",
10
"syn_aws"
11
]
12
}
13
},
14
"filter": {
15
"syn_aws": {
16
"type": "synonym",
17
"synonyms": [
18
"amazon, aws"
19
]
20
}
21
}
22
}
23
},
24
"mappings": {
25
"properties": {
26
"message": {
27
"type": "text",
28
"analyzer": "my_syn"
29
}
30
}
31
}
32
}
Copied!
앞의 예제와 동일하게 "Amazon Web Service", "AWS" 값을 가진 도큐먼트 두 개를 저장하고 각 도큐먼트의 _termvectors 를 확인 해 보겠습니다.
AWS, Amazon Web Service 도큐먼트 저장
1
PUT my_synonym/_doc/1
2
{ "message" : "Amazon Web Service" }
3
PUT my_synonym/_doc/2
4
{ "message" : "AWS" }
Copied!
request
response
1 도큐먼트 message 필드의 termvectors 확인
1
GET my_synonym/_termvectors/1?fields=message
Copied!
1 도큐먼트 message 필드의 termvectors 확인 결과
1
{
2
"_index" : "my_synonym",
3
"_type" : "_doc",
4
"_id" : "1",
5
"_version" : 1,
6
"found" : true,
7
"took" : 0,
8
"term_vectors" : {
9
"message" : {
10
"field_statistics" : {
11
"sum_doc_freq" : 6,
12
"doc_count" : 2,
13
"sum_ttf" : 6
14
},
15
"terms" : {
16
"amazon" : {
17
"term_freq" : 1,
18
"tokens" : [
19
{
20
"position" : 0,
21
"start_offset" : 0,
22
"end_offset" : 6
23
}
24
]
25
},
26
"aws" : {
27
"term_freq" : 1,
28
"tokens" : [
29
{
30
"position" : 0,
31
"start_offset" : 0,
32
"end_offset" : 6
33
}
34
]
35
},
36
"service" : {
37
"term_freq" : 1,
38
"tokens" : [
39
{
40
"position" : 2,
41
"start_offset" : 11,
42
"end_offset" : 18
43
}
44
]
45
},
46
"web" : {
47
"term_freq" : 1,
48
"tokens" : [
49
{
50
"position" : 1,
51
"start_offset" : 7,
52
"end_offset" : 10
53
}
54
]
55
}
56
}
57
}
58
}
59
}
Copied!
request
response
2 도큐먼트 message 필드의 termvectors 확인
1
GET my_synonym/_termvectors/2?fields=message
Copied!
2 도큐먼트 message 필드의 termvectors 확인 결과
1
{
2
"_index" : "my_synonym",
3
"_type" : "_doc",
4
"_id" : "2",
5
"_version" : 1,
6
"found" : true,
7
"took" : 0,
8
"term_vectors" : {
9
"message" : {
10
"field_statistics" : {
11
"sum_doc_freq" : 6,
12
"doc_count" : 2,
13
"sum_ttf" : 6
14
},
15
"terms" : {
16
"amazon" : {
17
"term_freq" : 1,
18
"tokens" : [
19
{
20
"position" : 0,
21
"start_offset" : 0,
22
"end_offset" : 3
23
}
24
]
25
},
26
"aws" : {
27
"term_freq" : 1,
28
"tokens" : [
29
{
30
"position" : 0,
31
"start_offset" : 0,
32
"end_offset" : 3
33
}
34
]
35
}
36
}
37
}
38
}
39
}
Copied!
두 도큐먼트 모두 "position" : 0 위치에 "aws", "amazon" 두개의 텀들이 모두 저장된 것을 확인할 수 있습니다. 이제 term 쿼리로 amazon 을 검색해도 두개 도큐먼트가 모두 검색이 됩니다. 이것은 한번 직접 실행 해 보시기 바랍니다.
동의어 여러 개를 입력 할 때는 "synonyms": [ ... ] 항목 안에 배열로 넣어도 되지만, 그 보다는 파일을 따로 만들어 관리하는 것이 편합니다. stop 토큰 필터와 마찬가지로 synonyms_path 항목에 config 디렉토리 기준의 상대 경로에 파일을 저장하고 경로명을 입력하면 됩니다. 동의어는 하나의 규칙당 한 줄씩 입력해야 하며 파일은 UTF-8로 인코딩 되어야 합니다.
다음은 "hop, jump", "quick, fast" user_dic/my_syn_dic.txt 에 저장해서 동의어 사전으로 사용하는 예제입니다.
config/user_dic 디렉토리 아래에 my_syn_dic.txt 파일 생성
1
$ echo 'quick, fast
2
hop, jump' > config/user_dic/my_syn_dic.txt
Copied!
synonyms_path 설정을 가진 my_synonym 인덱스 생성
1
PUT my_synonym
2
{
3
"settings": {
4
"analysis": {
5
"analyzer": {
6
"my_syn": {
7
"tokenizer": "whitespace",
8
"filter": [
9
"lowercase",
10
"syn_aws"
11
]
12
}
13
},
14
"filter": {
15
"syn_aws": {
16
"type": "synonym",
17
"synonyms_path": "user_dic/my_syn_dic.txt"
18
}
19
}
20
}
21
},
22
"mappings": {
23
"properties": {
24
"message": {
25
"type": "text",
26
"analyzer": "my_syn"
27
}
28
}
29
}
30
}
Copied!
이제 term 쿼리로 quickjump를 검색하면 hop, fast 도 검색이 됩니다.
quick, jump, hop, fast 를 포함하는 도큐먼트 저장
1
PUT my_synonym/_doc/1
2
{ "message": "Quick brown fox jump" }
3
PUT my_synonym/_doc/2
4
{ "message": "hop rabbit is fast" }
Copied!
request
response
term 쿼리로 quick, jump 검색
1
GET GET my_synonym/_search
2
{
3
"query": {
4
"bool": {
5
"must": [
6
{
7
"term": {
8
"message": "quick"
9
}
10
},
11
{
12
"term": {
13
"message": "jump"
14
}
15
}
16
]
17
}
18
}
19
}
Copied!
term 쿼리로 quick, jump 검색 결과
1
{
2
"took" : 370,
3
"timed_out" : false,
4
"_shards" : {
5
"total" : 1,
6
"successful" : 1,
7
"skipped" : 0,
8
"failed" : 0
9
},
10
"hits" : {
11
"total" : {
12
"value" : 2,
13
"relation" : "eq"
14
},
15
"max_score" : 0.42221838,
16
"hits" : [
17
{
18
"_index" : "my_synonym",
19
"_type" : "_doc",
20
"_id" : "1",
21
"_score" : 0.42221838,
22
"_source" : {
23
"message" : "Quick brown fox jump"
24
}
25
},
26
{
27
"_index" : "my_synonym",
28
"_type" : "_doc",
29
"_id" : "2",
30
"_score" : 0.42221838,
31
"_source" : {
32
"message" : "hop rabbit is fast"
33
}
34
}
35
]
36
}
37
}
Copied!
마지막으로 synonym 토큰 필터에는 추가적으로 다음과 같은 옵션들이 있습니다.
  • expand (true / false. 디폴트는 true)
    "expand": false 로 설정하게 되면 "synonyms": "aws, amazon" 같은 설정에 토큰들을 모두 저장하지 않고 맨 처음에 명시된 토큰 하나만 저장합니다. 앞의 설정은 "synonyms": "aws, amazon => aws" 로 설정한 것과 동일하게 동작합니다.
  • lenient (true / false. 디폴트는 false)
    "lenient": true 로 설정하면 synonym 설정에 오류가 있는 경우 오류가 있는 부분을 무시하고 실행합니다.
Copy link