23 апр. 2018 г.
Это третья статья из цикла про Elastic Search. Речь пойдет о настройке русской морфологии Elastic Search. Настройка морфологии происходит путем добавлления в elastic search специальных анализаторов. Анализаторы учитывают особенности языка и за счет этого улучшаются результаты поиска.
В Elastic Search есть стандартный плагин. Он работает из коробки и обеспечивает базовую морфологию. Возьмем запрос на создания индекса из предыдущей статьи. Здесь созжаются фильтры ru_stop и ru_stemmer, которые затем добавляются в анализатор my_synonyms
curl -X PUT \ http://localhost:9200/product \ -H 'Cache-Control: no-cache' \ -H 'Content-Type: application/json' \ -H 'Postman-Token: 9068558d-fd30-4610-0d2d-8ada239fbc1e' \ -d '{ "settings": { "analysis": { "filter": { "my_synonym_filter": { "type": "synonym", "synonyms": [ "шуруповерт, отвертка" ] }, "ru_stop": { "type": "stop", "stopwords": "_russian_" }, "ru_stemmer": { "type": "stemmer", "language": "russian" } }, "analyzer": { "my_synonyms": { "tokenizer": "standard", "filter": [ "lowercase", "my_synonym_filter", "ru_stop", "ru_stemmer" ] } } } } }'
Проверить работу анализатора русской морфологии можно таким образом:
curl -X POST \ http://localhost:9200/_analyze \ -H 'Cache-Control: no-cache' \ -H 'Content-Type: application/json' \ -H 'Postman-Token: a7ba7c82-642b-0b31-d2ef-1c644c6e249e' \ -d '{ "analyzer" : "russian", "text" : "Отвертка аккумуляторная ИНТЕРСКОЛ ОА-3,6Ф блистер (433.0.2.00) li-ion Номинальное напряжение, В 3,6 Частота вращения, об/мин 210 Макс. Крутящий момент, Нм 5 Число ступеней регулировки крутящего момента 15+1 Масса, кг 0,5 Особенности: Технология Li-ion, Редуктор с металлическими пластинами, компактность, светодиодный фонарь, индикатор заряда, LED-подсветка." }'
В результате текст бьется на токены, примерно так:
{ "tokens": [ { "token": "отвертк", "start_offset": 0, "end_offset": 8, "type": "<ALPHANUM>", "position": 0 }, { "token": "аккумуляторн", "start_offset": 9, "end_offset": 23, "type": "<ALPHANUM>", "position": 1 }, { "token": "интерскол", "start_offset": 24, "end_offset": 33, "type": "<ALPHANUM>", "position": 2 }, { "token": "о", "start_offset": 34, "end_offset": 36, "type": "<ALPHANUM>", "position": 3 }, ... ] }
Далее в поиске можно попробовать искать по токенам, записи будут возвращаться. По запросу "отвертк" должна будет вернуться запись. По запросу "отвер" вернется пустое множество. Также существует плагин с улучшеной морфологией русского языка. К сожалению, на момент написания статьи, он не портирован на Elastic Search 6.
Далее в статье будет использоваться Elastic Search 5.6.5
Запускаем Elastic Search 5.6.5 в docker:
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:5.6.5
Устанавливаем плагин:
docker exec -it bash elasticsearch elasticsearch-plugin install http://dl.bintray.com/content/imotov/elasticsearch-plugins/org/elasticsearch/elasticsearch-analysis-morphology/5.6.5/elasticsearch-analysis-morphology-5.6.5.zip
Важный момент. Я делал это в docker и плагин устанавливался автоматически. При этом во время ручной установки возникли проблемы.
docker-compose.yml:
version : '2' services: elasticsearch5: build: ./docker/elasticsearch5 container_name: elasticsearch5 ports: - 9200:9200 - 9300:9300
docker/elasticsearch5/Dockerfile:
FROM elasticsearch:5.6.5 RUN apt-get update RUN apt-get install -y mc RUN elasticsearch-plugin install http://dl.bintray.com/content/imotov/elasticsearch-plugins/org/elasticsearch/elasticsearch-analysis-morphology/5.6.5/elasticsearch-analysis-morphology-5.6.5.zip
Проверяем работу плагина:
curl -X POST \ http://localhost:9200/_analyze \ -H 'Content-Type: application/json' \ -d '{ "analyzer" : "russian_morphology", "text" : "Рукоятка крепится на шарнире. Можно выбрать либо прямое положение, либо пистолетное." }'
В отличии от стандартного анализатора, выводятся приведенные полные формы слов. Результат должен быть примерно такой:
{ "tokens": [ { "token": "рукоятка", "start_offset": 0, "end_offset": 8, "type": "<ALPHANUM>", "position": 0 }, { "token": "крепиться", "start_offset": 9, "end_offset": 17, "type": "<ALPHANUM>", "position": 1 }, { "token": "на", "start_offset": 18, "end_offset": 20, "type": "<ALPHANUM>", "position": 2 }, { "token": "шарнир", "start_offset": 21, "end_offset": 28, "type": "<ALPHANUM>", "position": 3 }, { "token": "можно", "start_offset": 30, "end_offset": 35, "type": "<ALPHANUM>", "position": 4 }, ... ] }
Создаем индекс
curl -X PUT \ http://localhost:9200/rustest \ -H 'Content-Type: application/json' \ -d '{ "settings": { "analysis": { "analyzer": { "my_analyzer": { "type": "custom", "tokenizer": "standard", "filter": ["lowercase", "russian_morphology", "english_morphology", "my_stopwords"] } }, "filter": { "my_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" } } } } }'
Создаем маппинг
curl -X PUT \ http://localhost:9200/rustest/_mapping/doc \ -H 'Cache-Control: no-cache' \ -H 'Content-Type: application/json' \ -H 'Postman-Token: 412756ab-518e-566c-97eb-401f6f9b8a03' \ -d '{ "properties": { "body": { "type": "text", "index": true, "search_analyzer": "my_analyzer", "analyzer": "my_analyzer", "term_vector": "with_positions_offsets_payloads" } } }'
Добавляем документ
curl -X PUT \ http://localhost:9200/rustest/doc/1 \ -H 'Content-Type: application/json' \ -d '{"body": "Рукоятка крепится на шарнире. Можно выбрать либо прямое положение, либо пистолетное."}'
Пробуем искать по нему:
curl -X POST \ 'http://localhost:9200/rustest/doc/_search?pretty=true' \ -H 'Content-Type: application/json' \ -d '{ "query": { "match": { "body": "крепится" } } }'
Все запросы из статьи оформлены в виде Postman коллекции. Скачать можно тут: elastic-search-russian-morfology.postman_collection.json
На этом пока все. Спасибо за внимание!