# 6.6.3 Synonym

&#x20; 검색 서비스에 따라서 **동의어** 검색을 제공해야 하는 경우가 있습니다. 예를 들면 클라우드 서비스 관련 정보를 검색하는 시스템에서 "AWS" 라는 단어를 검색했을 때 "Amazon" 또는 한글 "아마존" 도 같이 검색을 하도록 하면 관련된 정보를 더 많이 찾을 수 있을 것입니다. 이 때 **Synonym** 토큰 필터를 사용하면 텀의 동의어 저장이 가능합니다.&#x20;

&#x20; 동의어를 설정하는 옵션은 `synonyms` 항목에서 직접 동의어 목록을 입력하는 방법과 동의어 사전 파일을 만들어 `synonyms_path` 로 지정하는 방법이 있습니다. 동의어 사전 명시 규칙에는 다음의 것들이 있습니다.

* `"A, B => C"` : 왼쪽의 A, B 대신 오른쪽의 C 텀을 저장합니다. A, B 로는 C 의 검색이 가능하지만 C 로는 A, B 가 검색되지 않습니다.
* `"A, B"` : A, B 각 텀이 A 와 B 두개의 텀을 모두 저장합니다. A 와 B 모두 서로의 검색어로 검색이 됩니다.

&#x20; 다음은 **my\_synonym** 인덱스에 `"amazon => aws"` 으로 동의어를 지정하는 예제입니다.

{% code title=""amazon => aws" 동의어를 지정하는 my\_synonym 인덱스 생성" %}

```javascript
PUT my_synonym
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_syn": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "syn_aws"
          ]
        }
      },
      "filter": {
        "syn_aws": {
          "type": "synonym",
          "synonyms": [
            "amazon => aws"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": {
        "type": "text",
        "analyzer": "my_syn"
      }
    }
  }
}
```

{% endcode %}

&#x20; 이제 여기에 **"Amazon Web Service"**, **"AWS"** 값을 가진 도큐먼트 두 개를 저장하고 각 도큐먼트의 `_termvectors` 를 확인 해 보겠습니다.

{% code title="AWS, Amazon Web Service 도큐먼트 저장" %}

```javascript
PUT my_synonym/_doc/1
{ "message" : "Amazon Web Service" }
PUT my_synonym/_doc/2
{ "message" : "AWS" }
```

{% endcode %}

{% tabs %}
{% tab title="request" %}
{% code title="1 도큐먼트 message 필드의 termvectors 확인" %}

```javascript
GET my_synonym/_termvectors/1?fields=message
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="1 도큐먼트 message 필드의 termvectors 확인 결과" %}

```javascript
{
  "_index" : "my_synonym",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "took" : 9,
  "term_vectors" : {
    "message" : {
      "field_statistics" : {
        "sum_doc_freq" : 4,
        "doc_count" : 2,
        "sum_ttf" : 4
      },
      "terms" : {
        "aws" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 6
            }
          ]
        },
        "service" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 2,
              "start_offset" : 11,
              "end_offset" : 18
            }
          ]
        },
        "web" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 1,
              "start_offset" : 7,
              "end_offset" : 10
            }
          ]
        }
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="request" %}
{% code title="2 도큐먼트 message 필드의 termvectors 확인" %}

```javascript
GET my_synonym/_termvectors/2?fields=message
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="2 도큐먼트 message 필드의 termvectors 확인 결과" %}

```javascript
{
  "_index" : "my_synonym",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 1,
  "found" : true,
  "took" : 0,
  "term_vectors" : {
    "message" : {
      "field_statistics" : {
        "sum_doc_freq" : 4,
        "doc_count" : 2,
        "sum_ttf" : 4
      },
      "terms" : {
        "aws" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 3
            }
          ]
        }
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; 1 도큐먼트의 **"Amazon Web Service"**&#xAC00; **amazon** 대신 **"aws"**, **"web"**, **"service"** 로 저장된 것을 확인할 수 있습니다. 다음은 각각 **term** 쿼리로 **aws**, **amazon** 을 검색한 결과와 **match** 쿼리로 **amazon** 을 검색한 결과입니다.

{% tabs %}
{% tab title="request" %}
{% code title="term 쿼리로 aws 검색" %}

```javascript
GET my_synonym/_search
{
  "query": {
    "term": {
      "message": "aws"
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="term 쿼리로 aws 검색 결과" %}

```javascript
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.22920427,
    "hits" : [
      {
        "_index" : "my_synonym",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.22920427,
        "_source" : {
          "message" : "AWS"
        }
      },
      {
        "_index" : "my_synonym",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.1513613,
        "_source" : {
          "message" : "Amazon Web Service"
        }
      }
    ]
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="request" %}
{% code title="term 쿼리로 amazon 검색" %}

```javascript
GET my_synonym/_search
{
  "query": {
    "term": {
      "message": "amazon"
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="term 쿼리로 amazon 검색 결과" %}

```javascript
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 0,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [ ]
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="request" %}
{% code title="match 쿼리로 amazon 검색" %}

```javascript
GET GET my_synonym/_search
{
  "query": {
    "match": {
      "message": "amazon"
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="match 쿼리로 amazon 검색 결과" %}

```javascript
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.22920427,
    "hits" : [
      {
        "_index" : "my_synonym",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.22920427,
        "_source" : {
          "message" : "AWS"
        }
      },
      {
        "_index" : "my_synonym",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.1513613,
        "_source" : {
          "message" : "Amazon Web Service"
        }
      }
    ]
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; 첫 번째 쿼리와 마지막 세 번째 쿼리의 결과가 동일합니다.

&#x20; **term** 쿼리는 검색어에 애널라이저를 적용하지 않고 그대로 검색하기 때문에 **term** 쿼리로 **aws** 를 검색하면 두개의 도큐먼트가 모두 검색되고 **amazon**을 검색 하면 검색이 되지 않습니다. **match** 쿼리는 검색어 **amazon**도 **my\_syn** 애널라이저가 적용이 되어 **aws** 로 변환하여 검색을 하기 때문에 **aws**로 검색을 한 것과 같은 결과가 나타납니다.

&#x20; 이번에는 **my\_synonym** 인덱스에 `"amazon, aws"`  로 동의어를 지정하는 예제입니다. 기존의 **my\_synonym** 인덱스를 먼저 삭제하고 입력합니다.

{% code title=""amazon, aws" 동의어를 지정하는 my\_synonym 인덱스 생성" %}

```javascript
PUT my_synonym
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_syn": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "syn_aws"
          ]
        }
      },
      "filter": {
        "syn_aws": {
          "type": "synonym",
          "synonyms": [
            "amazon, aws"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": {
        "type": "text",
        "analyzer": "my_syn"
      }
    }
  }
}
```

{% endcode %}

&#x20; 앞의 예제와 동일하게 **"Amazon Web Service"**, **"AWS"** 값을 가진 도큐먼트 두 개를 저장하고 각 도큐먼트의 `_termvectors` 를 확인 해 보겠습니다.

{% code title="AWS, Amazon Web Service 도큐먼트 저장" %}

```javascript
PUT my_synonym/_doc/1
{ "message" : "Amazon Web Service" }
PUT my_synonym/_doc/2
{ "message" : "AWS" }
```

{% endcode %}

{% tabs %}
{% tab title="request" %}
{% code title="1 도큐먼트 message 필드의 termvectors 확인" %}

```javascript
GET my_synonym/_termvectors/1?fields=message
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="1 도큐먼트 message 필드의 termvectors 확인 결과" %}

```javascript
{
  "_index" : "my_synonym",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "took" : 0,
  "term_vectors" : {
    "message" : {
      "field_statistics" : {
        "sum_doc_freq" : 6,
        "doc_count" : 2,
        "sum_ttf" : 6
      },
      "terms" : {
        "amazon" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 6
            }
          ]
        },
        "aws" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 6
            }
          ]
        },
        "service" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 2,
              "start_offset" : 11,
              "end_offset" : 18
            }
          ]
        },
        "web" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 1,
              "start_offset" : 7,
              "end_offset" : 10
            }
          ]
        }
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="request" %}
{% code title="2 도큐먼트 message 필드의 termvectors 확인" %}

```javascript
GET my_synonym/_termvectors/2?fields=message
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="2 도큐먼트 message 필드의 termvectors 확인 결과" %}

```javascript
{
  "_index" : "my_synonym",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 1,
  "found" : true,
  "took" : 0,
  "term_vectors" : {
    "message" : {
      "field_statistics" : {
        "sum_doc_freq" : 6,
        "doc_count" : 2,
        "sum_ttf" : 6
      },
      "terms" : {
        "amazon" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 3
            }
          ]
        },
        "aws" : {
          "term_freq" : 1,
          "tokens" : [
            {
              "position" : 0,
              "start_offset" : 0,
              "end_offset" : 3
            }
          ]
        }
      }
    }
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; 두 도큐먼트 모두 `"position" : 0` 위치에 **"aws"**, **"amazon"** 두개의 텀들이 모두 저장된 것을 확인할 수 있습니다. 이제 **term** 쿼리로 **amazon** 을 검색해도 두개 도큐먼트가 모두 검색이 됩니다. 이것은 한번 직접 실행 해 보시기 바랍니다.

&#x20; 동의어 여러 개를 입력 할 때는 `"synonyms": [ ... ]` 항목 안에 배열로 넣어도 되지만, 그 보다는 파일을 따로 만들어 관리하는 것이 편합니다. **stop** 토큰 필터와 마찬가지로 **synonyms\_path** 항목에 **config** 디렉토리 기준의 상대 경로에 파일을 저장하고 경로명을 입력하면 됩니다. 동의어는 하나의 규칙당 **한 줄씩** 입력해야 하며 파일은 **UTF-8**로 인코딩 되어야 합니다.

&#x20; 다음은 **"hop, jump"**, **"quick, fast"** 를 **user\_dic/my\_syn\_dic.txt** 에 저장해서 동의어 사전으로 사용하는 예제입니다.

{% code title="config/user\_dic 디렉토리 아래에 my\_syn\_dic.txt 파일 생성" %}

```bash
$ echo 'quick, fast
hop, jump' > config/user_dic/my_syn_dic.txt
```

{% endcode %}

{% code title="synonyms\_path 설정을 가진 my\_synonym 인덱스 생성" %}

```javascript
PUT my_synonym
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_syn": {
          "tokenizer": "whitespace",
          "filter": [
            "lowercase",
            "syn_aws"
          ]
        }
      },
      "filter": {
        "syn_aws": {
          "type": "synonym",
          "synonyms_path": "user_dic/my_syn_dic.txt"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "message": {
        "type": "text",
        "analyzer": "my_syn"
      }
    }
  }
}
```

{% endcode %}

&#x20; 이제 **term** 쿼리로 **quick** 과 **jump**를 검색하면 **hop**, **fast** 도 검색이 됩니다.

{% code title="quick, jump, hop, fast 를 포함하는 도큐먼트 저장" %}

```javascript
PUT my_synonym/_doc/1
{ "message": "Quick brown fox jump" }
PUT my_synonym/_doc/2
{ "message": "hop rabbit is fast" }
```

{% endcode %}

{% tabs %}
{% tab title="request" %}
{% code title="term 쿼리로 quick, jump 검색" %}

```javascript
GET GET my_synonym/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "message": "quick"
          }
        },
        {
          "term": {
            "message": "jump"
          }
        }
      ]
    }
  }
}
```

{% endcode %}
{% endtab %}

{% tab title="response" %}
{% code title="term 쿼리로 quick, jump 검색 결과" %}

```javascript
{
  "took" : 370,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.42221838,
    "hits" : [
      {
        "_index" : "my_synonym",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.42221838,
        "_source" : {
          "message" : "Quick brown fox jump"
        }
      },
      {
        "_index" : "my_synonym",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 0.42221838,
        "_source" : {
          "message" : "hop rabbit is fast"
        }
      }
    ]
  }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

&#x20; 마지막으로 **synonym** 토큰 필터에는 추가적으로 다음과 같은 옵션들이 있습니다.

* **expand** (true / false. 디폴트는 **true**)

  `"expand": false` 로 설정하게 되면 `"synonyms": "aws, amazon"` 같은 설정에 토큰들을 모두 저장하지 않고 맨 처음에 명시된 토큰 하나만 저장합니다. 앞의 설정은 `"synonyms": "aws, amazon => aws"` 로 설정한 것과 동일하게 동작합니다.
* **lenient** (true / false. 디폴트는 **false**)

  `"lenient": true` 로 설정하면 synonym 설정에 오류가 있는 경우 오류가 있는 부분을 무시하고 실행합니다.

&#x20;&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://esbook.kimjmin.net/06-text-analysis/6.6-token-filter/6.6.3-synonym.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
