# Морфология с Hunspell не работает при поиске

**URL:** https://discuss.elastic.co/t/hunspell/260189
**Category:** Вопросы на русском языке
**Created:** [January 5, 2021, 10:40am UTC](https://discuss.elastic.co/t/hunspell/260189 "2021-01-05T10:40:16Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![DimanG](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dimang/32/81770_2.png) [@DimanG](https://discuss.elastic.co/u/DimanG)
#### Post date: [January 5, 2021, 10:40am UTC](https://discuss.elastic.co/t/hunspell/260189/1 "2021-01-05T10:40:16Z")

</div>

Всем доброго дня!  
В эластике новичок. Остался один шаг до начала использования - побороть морфологию. Проблема схожа с описанной в этой теме, но у меня само не заработало: [Не получается побороть морфологию](https://discuss.elastic.co/t/topic/182967/2)  
По совету опытных товарищей выбрал Hunspell (с пересобранным russian morphology Эластик отказался запускаться), имеем следующее:

```auto
    PUT /search_index
    {
    "settings": {
        "analysis" : {
            "analyzer" : {
                "ru" : {
                    "type": "custom", //добавил позже, результат описан ниже
                    "tokenizer" : "standard",
                    "filter" : ["lowercase", "ru_RU", "russian_stop"]
                }
            },
            "filter" : {
                "ru_RU" : {
                    "type" : "hunspell",
                    "locale" : "ru_RU",
                    "dedup" : true
                },
                "russian_stop": {
                  "type": "stop",
                  "stopwords": "_russian_"
                }
              }
            }
         }
      }
    }

```

Маппинг (полей на самом деле больше)

```auto
    PUT search_index/_mappings
    {
      "properties": {
        "title": {
          "type": "text",
          "analyzer": "ru"
        }
       }
    }

```

Анализатор подключен:

```auto
    POST search_index/_analyze
    {
      "text": "боярышника настойку",
      "field": "title"
    // "analyzer": "ru" - с этим тоже работает
    }

```

выдаёт

```auto
    {
  "tokens" : [
    {
      "token" : "боярышник",
      "start_offset" : 0,
      "end_offset" : 10,
      "type" : "<ALPHANUM>",
      "position" : 0
    },
    {
      "token" : "настойка",
      "start_offset" : 11,
      "end_offset" : 19,
      "type" : "<ALPHANUM>",
      "position" : 1
     }
     ]
    }

```

После добавления в settings 'type': 'custom' перестал индексировать с ошибкой

# {"error":{"root\_cause":[{"type":"illegal\_argument\_exception","reason":"Mapper for [mnn\_title] conflicts with existing mapper:\n\tCannot update parameter [analyzer] from [ru] to [default]"}],"type":"illegal\_argument\_exception","reason":"Mapper for [mnn\_title] conflicts with existing mapper:\n\tCannot update parameter [analyzer] from [ru] to [default]"},"status":400}

До этого индексировал, но ничего не искал по морфологическим запросам.

Прошу помочь, ибо уже не терпится испытать этот замечательный инструмент в деле. Перепробовал всё.

Заранее спасибо.

---

<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: [January 5, 2021, 4:08pm UTC](https://discuss.elastic.co/t/hunspell/260189/2 "2021-01-05T16:08:40Z")

</div>

> [@DimanG](#):
>
> Маппинг (полей на самом деле больше)

Одно из этих полей называется `mnn_title`, и оно уже существует в индексе, но имеет настройки, отличающиеся от настроек в вашей команде. После того, как поле добавлено в маппинг, его нельзя удалить, и большинство настроек нельзя изменить. Об этом вам эта ошибка и сообщает: `Mapper for [mnn_title] conflicts with existing mapper: Cannot update parameter [analyzer] from [ru] to [default]`.

Поэтому, когда вы экспериментируете с настройками, я бы посоветовал удалять индекс при каждом изменении маппинга или настроек.

Можно также не добавлять существующее поле в ` PUT search_index/_mappings` или проверить, что поле, которое добавлятся, имеет те же самые настройки, что и поле, существующее в индексе.

---

<div class="post-metadata">

### Author: ![DimanG](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dimang/32/81770_2.png) [@DimanG](https://discuss.elastic.co/u/DimanG)
#### Post date: [January 5, 2021, 4:59pm UTC](https://discuss.elastic.co/t/hunspell/260189/3 "2021-01-05T16:59:33Z")

</div>

Спасибо за быстрый ответ.

Индекс удаляю при каждом витке экспериментов (DELETE /search\_index). Создавать пробовал как с указанием маппинга (PUT search\_index/\_mappings), так и без него. Когда без него - при автомаппинге - морфология не работает при поиске. Когда с явным заданием маппинга - либо не добавляется из-за конфликта анализаторов, либо что-то ещё. Индексировать пробовал как поштучно, так и при помощи bulk.  
Существует ли какой стопудово рабочий порядок 1) создания индекса 2) задания настроек анализатора 3) задания маппинга (если я правильно понял, без него не будет работать анализатор на индексируемых документах) , при котором всё заведётся? Хотя бы для такого простого примера, как у меня.  
Ругается на mnn\_title видимо потому, что он попадается первее, если его убрать - будет так же ругаться на все остальные поля. При индексации я просто добавляю документ, и никакие дополнительные настройки не указываю. Нужно ли как-то учитывать анализатор при индексировании документов?

---

<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: [January 5, 2021, 5:12pm UTC](https://discuss.elastic.co/t/hunspell/260189/4 "2021-01-05T17:12:32Z")

</div>

> [@DimanG](#):
>
> Существует ли какой стопудово рабочий порядок 1) создания индекса 2) задания настроек анализатора 3) задания маппинга (если я правильно понял, без него не будет работать анализатор на индексируемых документах) , при котором всё заведётся?

Да, проще всего делать 1-3 в одной команде:

```auto
DELETE test

PUT test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ru": {
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "ru_RU",
            "russian_stop"
          ]
        }
      },
      "filter": {
        "ru_RU": {
          "type": "hunspell",
          "locale": "ru_RU",
          "dedup": true
        },
        "russian_stop": {
          "type": "stop",
          "stopwords": "_russian_"
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "title": {
        "type": "text",
        "analyzer": "ru"
      }
    }
  }
}

PUT test/_doc/1
{
  "title": "А работает ли он с русским языком"
}

GET test/_search
{
  "query": {
    "match": {
      "title": "язык"
    }
  }
}

```

---

<div class="post-metadata">

### Author: ![DimanG](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dimang/32/81770_2.png) [@DimanG](https://discuss.elastic.co/u/DimanG)
#### Post date: [January 5, 2021, 5:23pm UTC](https://discuss.elastic.co/t/hunspell/260189/5 "2021-01-05T17:23:02Z")

</div>

Ваш пример отлично работает! Вся разница в том, что индексируемые документы я добавляю при помощи API (elasticsearch-php), видимо, дело в нём. Но никакой маппинг в коде не упоминается при индексировании, и код выглядит примерно следующим образом:

```auto
$client = ClientBuilder::create()->build();
$params = [
    'index' => 'my_index',
    'type' => 'my_type',
    'id' => 'my_id',
    'body' => ['testField' => 'abc']
];

$response = $client->index($params);
print_r($response);

```

Исходники модуля глубоко не копал, но может будет подсказка, в каком направлении копать?

---

<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: [January 5, 2021, 5:28pm UTC](https://discuss.elastic.co/t/hunspell/260189/6 "2021-01-05T17:28:17Z")

</div>

> [@DimanG](#):
>
> в каком направлении копать?

Копать надо [тут](https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index_management.html#_create_an_index_2).

---

<div class="post-metadata">

### Author: ![DimanG](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/dimang/32/81770_2.png) [@DimanG](https://discuss.elastic.co/u/DimanG)
#### Post date: [January 5, 2021, 5:58pm UTC](https://discuss.elastic.co/t/hunspell/260189/7 "2021-01-05T17:58:34Z")

</div>

Чудеса! Копание ничего не дало, но чутьём удалил в bulk '\_type' =\> 'drugs' и всё заработало! Хотя при штучном индексировании ругается на этот параметр и без него не даёт.

@Igor_Motov'у большое спасибо за участие!

Upd: параметр \_type брал из документации elasticsearch-php, на сайте в разделе API для PHP этого параметра нет.

---

<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: [February 2, 2021, 5:58pm UTC](https://discuss.elastic.co/t/hunspell/260189/8 "2021-02-02T17:58:44Z")

</div>

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