Русский поиск в Elasticsearch

Есть необходимость искать в тексте не просто целиком слово, а с морфологическим разбором, например при запросе "документы" так же были найдены документы со словами "документ", "документов", "документами" и т.п. Как оказалось дойти до реализации с первого раза не так уж и просто. Но возможно.

Подготовка

Для версии Elasticsearch до 6 есть плагин от IMotov. Для более старшей версии (в моем случае для 7.6) — можно использовать плагин от Fooger. В составе плагина analysis-morphology есть плагин russian_morphology (и другие), который как раз и будет заниматься леммингом и другим анализом данных

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

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

Образ

ES я собираю из докера через Dockerfile

FROM elasticsearch:7.6.0

RUN bin/elasticsearch-plugin install https://github.com/fooger/elasticsearch-analysis-morphology/raw/master/analysis-morphology-7.6.0.zip

в docker-compose.yml можно стартануть как описано тут, но с использованием своего контекста

главное не забыть после первого запуска выполнить из докера (или от докера) команду sysctl -w vm.max_map_count=262144

собираем docker-compose build запускаем docker-compose up -d

Elasticsearch

Теперь все дело в волшебных пузырьках. При создании индекса необходимо передать правильные настройки индекса с указанием анализатора и создать на основе настроек маппинг.

PUT /myindex

{
    "settings": {
        "index": {
            "analysis": {
                "analyzer": {
                    "my_search_analyzer": {
                        "type": "custom",
                        "tokenizer": "standard",
                        "filter": [
                            "lowercase",
                            "search_synonym",
                            "russian_morphology",
                            "english_morphology",
                            "ru_stopwords"
                        ]
                    }
                },
                "filter": {
                    "search_synonym": {
                        "ignore_case": "true",
                        "type": "synonym",
                        "synonyms": [
                            "пончо,накидка"
                        ]
                    },
                    "ru_stopwords": {
                        "type": "stop",
                        "stopwords": "а,без,более,бы,был,была,были,было,быть,в,вам,вас,весь,во,вот,все,всего,всех,вы,где,да,даже,для,до,его,ее,если,есть,еще,же,за,здесь,и,из,или,им,их,к,как,ко,когда,кто,ли,либо,мне,может,мы,на,надо,наш,не,него,нее,нет,ни,них,но,ну,о,об,однако,он,она,они,оно,от,очень,по,под,при,с,со,так,также,такой,там,те,тем,то,того,тоже,той,только,том,ты,у,уже,хотя,чего,чей,чем,что,чтобы,чье,чья,эта,эти,это,я,a,an,and,are,as,at,be,but,by,for,if,in,into,is,it,no,not,of,on,or,such,that,the,their,then,there,these,they,this,to,was,will,with"
                    }
                }
            }
        }
    },
    "mappings": {
        "properties": {
            "title": {
                "type": "text",
                "analyzer": "my_search_analyzer"
            },
            "content": {
                "type": "text",
                "analyzer": "my_search_analyzer"
            },
            "description": {
                "type": "text",
                "analyzer": "my_search_analyzer"
            },
            "type": {
                "type": "keyword"
            }
        }
    }
}

Ошибки

Ошибки, какие были по пути следования

  • "No handler for type [string] declared on field [title]" Неверное указание в mappings типа поля string. С определенной версии elasticsearch заменили string на text
  • Mapper for [title] conflicts with existing mapping: возможно вы пытаетесь обновить уже существуюший индекс. В любом случае придется делать реиндекс. Либо создать новый индекс.

Источники

Leave a comment

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