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

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

    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_"
                }
              }
            }
         }
      }
    }

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

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

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

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

выдаёт

    {
  "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}

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

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

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

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

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

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

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

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

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

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": "язык"
    }
  }
}

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

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

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

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

Копать надо тут.

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

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

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

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