# Иерархическое применение синонимов

**URL:** <https://discuss.elastic.co/t/topic/202995>\
**Category:** Вопросы на русском языке\
**Created:** [October 10, 2019, 10:00am UTC](https://discuss.elastic.co/t/topic/202995 "2019-10-10T10:00:41Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![LLIyMAXEP](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/lliymaxep/32/55678_2.png) [@LLIyMAXEP](https://discuss.elastic.co/u/LLIyMAXEP)\
**Post date:** [October 10, 2019, 10:00am UTC](https://discuss.elastic.co/t/topic/202995/1 "2019-10-10T10:00:41Z")

</div>

Добрый день.

Немного запутался с концепцией multiword synonyms. Объясню на примерах.  
Индекс и документы:

```
PUT test_index1
{
  "mappings": {
    "doc": {
      "properties": {
        "full_text": {
          "type": "text",
          "term_vector": "with_positions_offsets",
          "search_analyzer": "main_analyzer",
          "analyzer": "index_analyzer"
        }
      }
    }
  },
  "settings": {
    "index": {
      "analysis": {
        "filter": {
          "synonyms": {
            "type": "synonym_graph",
            "synonyms": [
              "выписка из егрюл, выписка егрюл",
              "единый государственный реестр юридический лицо, егрюл"
            ],
            "expand": true
          }
        },
        "analyzer": {
          "index_analyzer": {
            "filter": [
              "lowercase"
            ],
            "type": "custom",
            "tokenizer": "standard"
          },
          "main_analyzer": {
            "filter": [
              "lowercase",
              "synonyms"
            ],
            "char_filter": [
              "delimiter_char_filter"
            ],
            "type": "custom",
            "tokenizer": "standard"
          }
        },
        "char_filter": {
          "delimiter_char_filter": {
            "type": "mapping",
            "mappings": [
              "/=>_",
              "-=>_"
            ]
          }
        }
      }
    }
  }
}

PUT test_index1/doc/1
{
  "full_text": "об особенность оформление выписка из егрюл"
}

PUT test_index1/doc/2
{
  "full_text": "выписка единый государственный реестр юридический лицо"
}

PUT test_index1/doc/3
{
  "full_text": "единый государственный реестр юридический лицо"
}

```

Поиск:

```
POST test_index1/_search?search_type=dfs_query_then_fetch
{
  "query": {
    "match": {
      "full_text": {
        "query": "выписка егрюл",
        "operator": "or"
      }
    }
  },
  "highlight": {
    "fields": {
      "full_text": {}
    }
  }
}

```

Я ожидаю, что при поиске у меня найдутся все документы, так как синоним "егрюл" должен поменяться на "единый государственный реестр юридический лицо", но магии не происходит и находится только первый документ. Есть какие-то способы побороть проблему средствами эластика? Или нам делать предобработку синонимов в коде?

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 10, 2019, 11:49am UTC](https://discuss.elastic.co/t/topic/202995/2 "2019-10-10T11:49:37Z")

</div>

Спасибо за хорошие пример. Давайте разбираться. Посмотрим что у нас происходит с запросом:

```auto
POST test_index1/_validate/query?explain
{
  "query": {
    "match": {
      "full_text": {
        "query": "выписка егрюл",
        "operator": "or"
      }
    }
  }
}

```

получаем:

```auto
{
...
      "explanation" : """(full_text:"выписка из егрюл" full_text:"выписка егрюл")"""
...
}

```

Почему это происходит? Потому что мы применили первую строку из синонимов:  
`"выписка из егрюл, выписка егрюл"`, синонимы рекурсивно не применяются и мы ищем каждый найденный синоним как строку.

---

<div class="post-metadata">

**Author:** ![LLIyMAXEP](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/lliymaxep/32/55678_2.png) [@LLIyMAXEP](https://discuss.elastic.co/u/LLIyMAXEP)\
**Post date:** [October 10, 2019, 12:22pm UTC](https://discuss.elastic.co/t/topic/202995/3 "2019-10-10T12:22:42Z")

</div>

Игорь, спасибо, это как раз мне понятно. Нет ли такого подхода, чтобы синонимы, состоящие из нескольких слов, применялись рекурсивно?

До этого мы применяли подход с simple contraction при индексации, но такой подход при индексации заменяет многословные синонимы на 1 слово, что тоже накладывает свои ограничения при поиске. Сейчас кажется, что synonym\_graph + search\_analyzer - самое оптимальное решение, но могу ошибаться.

Ещё я пробовал подход, когда мы добавляем 2 фильтра синонимов, первый - с "выписка из егрюл, выписка егрюл", второй с "единый государственный реестр юридический лицо, егрюл", тогда в pipeline обработки вроде всё заменяется как надо, но это опять же накладывает на нас обязанность разделять синонимы на 2 группы.

Если нет возможности рекурсивной подстановки синонимов через elasticsearch/lucene, будем делать предобработку рекурсивную наших синонимов на 1-2 уровня вложенности. Спасибо ещё раз.

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 10, 2019, 12:26pm UTC](https://discuss.elastic.co/t/topic/202995/4 "2019-10-10T12:26:36Z")

</div>

Я не очень понимаю, что вы хотите добиться. Если честно, я не понимаю причин по которым вы добавили первую строку синонимов.

---

<div class="post-metadata">

**Author:** ![LLIyMAXEP](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/lliymaxep/32/55678_2.png) [@LLIyMAXEP](https://discuss.elastic.co/u/LLIyMAXEP)\
**Post date:** [October 10, 2019, 1:17pm UTC](https://discuss.elastic.co/t/topic/202995/5 "2019-10-10T13:17:21Z")

</div>

Есть исторически накопленная база синонимов, которые раньше применялись в поиске на другом движке. Предположим, что первая строчка синонимов это "выписка егрюл, оформить выписка егрюл, запросить егрюл, запросить выписка егрюл", не просто добавляем "из", а чуть сложнее строка. При этом, например, синонимы уровня "выписка, запросить, запросить выписка, оформить" нас могут не устраивать по каким-то причинам, связанным с конкретным набором наших документов и применяться могут в контексте только с "егрюл" (или каким-то другим словом, которое само по себе является аббревиатурой, которая добавлена так же в синонимы).

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 10, 2019, 1:29pm UTC](https://discuss.elastic.co/t/topic/202995/6 "2019-10-10T13:29:39Z")

</div>

Это подробное описание того, как ваша система не работает в данный момент и историческая справка. Я теперь понимаю, почему вы добавили первую строку - потому что так было в прошлой системе. Но я, все еще, не очень понимаю, что вы хотите добиться.

---

<div class="post-metadata">

**Author:** ![LLIyMAXEP](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/lliymaxep/32/55678_2.png) [@LLIyMAXEP](https://discuss.elastic.co/u/LLIyMAXEP)\
**Post date:** [October 10, 2019, 1:40pm UTC](https://discuss.elastic.co/t/topic/202995/7 "2019-10-10T13:40:21Z")

</div>

Название документа: "выписка единый государственный реестр юридический лицо".

Пользователь ищет: "выписка егрюл" или "запросить егрюл".  
При этом данный документ не находится, так как вы уже говорили, срабатывает синоним на "выписка егрюл", но подстановки "егрюл, единый государственный реестр юридический лицо" не происходит.

А хотелось бы, чтобы он находился.

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 10, 2019, 1:44pm UTC](https://discuss.elastic.co/t/topic/202995/8 "2019-10-10T13:44:12Z")

</div>

Эту часть я понимаю, но ее очень просто достичь убрав первую строку из списка синонимов из вашего примера. Мне хотелось бы понять, почему вам такой подход не подходит.

---

<div class="post-metadata">

**Author:** ![LLIyMAXEP](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/lliymaxep/32/55678_2.png) [@LLIyMAXEP](https://discuss.elastic.co/u/LLIyMAXEP)\
**Post date:** [October 10, 2019, 1:52pm UTC](https://discuss.elastic.co/t/topic/202995/9 "2019-10-10T13:52:11Z")

</div>

Если убрать эту строчку, то вот такой вариант запроса вернёт пустой результат:

```
POST test_index1/_search?search_type=dfs_query_then_fetch    
    {
      "query": {
        "match": {
          "full_text": {
            "query": "запросить егрюл",
            "minimum_should_match": "3<75%"
          }
        }
      },
      "highlight": {
        "fields": {
          "full_text": {}
        }
      }
    }

```

При замене or на and или добавлении minimum\_should\_match больше 1 получаем 0 результатов. Реальный запрос в разы сложнее, там и minimum\_should\_match, и match\_phrase и так далее.

В любом случае, как я понял, нам нужно именно перерабатывать словарь синонимов, а не искать решение с помощью elasticsearch, верно?

---

<div class="post-metadata">

**Author:** ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)\
**Post date:** [October 10, 2019, 3:20pm UTC](https://discuss.elastic.co/t/topic/202995/10 "2019-10-10T15:20:09Z")

</div>

> [@LLIyMAXEP](#):
>
> В любом случае, как я понял, нам нужно именно перерабатывать словарь синонимов, а не искать решение с помощью elasticsearch, верно?

Если вы хотите искать решение с помощью elasticsearch, то нужно более точно определить проблему для которой мы ищем это решение. Например, если у вас в запросе только 2 слова, то minimum\_should\_match больше 2-х не имеет никакого смысла. То есть, хотелось бы понять, откуда 3 там взялось и хорошее ли значение это для elasticsearch.

Если вы хотите засунуть elasticsearch в прокрустово ложе старой системы, то надо лучше разобраться, как старая система работает, или хотя бы понять, что вы заменяете. По той информации, которая пока появилась, мне кажется, что фильтр `synonym` вместо `synonym_graph` будет вести себя более похоже на поведение вашей старой системы.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [November 7, 2019, 3:20pm UTC](https://discuss.elastic.co/t/topic/202995/11 "2019-11-07T15:20:14Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
