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
На этом пока все. Спасибо за внимание!