Русская морфология


(Dmitriy Glukhov) #1

Здравствуйте.
Я использую ES версии 1.7.0 + elasticsearch-analysis-morphology (полагаю, версии 1.2.1).
В настройках я имею:


"analyzer": {
"ru_analyzer": {
"filter": [
"lowercase",
"russian_morphology",
"english_morphology",
"my_stopwords"
],
"type": "custom",
"tokenizer": "standard"
}
}
Мапинг для типа:
"name": {
  "type": "string",
  "store": true,
  "analyzer": "ru_analyzer"
}
Проблема заключается в поиске русских слов по корню с одним или несколькими суффиксами и окончанием. Например, имеем name="Парковые территории". В поисковую строку вводим "парк" и видим пустой результат; вводим "парков" - запись найдена. Standart токенайзер разбирает "Парковые" на "парков", но при этом "Важнейшие" он разберет до "важн". Как можно решить мою проблему?

(Igor Motov) #2

Я думаю, что этот вопрос лучше всего задать автору русского морфологического анализатора тут - https://github.com/AKuznetsov/russianmorphology


(Dmitriy Glukhov) #3

Понимаю, что лучше обратиться к первоисточнику. Но даже если будут исправления на том уровне, то все равно нужно будет их как-то перенести в плагин Эластика. Даже если все получится, то это займет много времени.
Интересует возможность решить проблему каким-то обходным путем, если это возможно. Я лично вижу два варианта: EdgeNGram, но тогда мы будем получать в результатах много лишнего; и второй - пополняемый словарь синонимов для search-анализатора, т.е. ru_analyzer использовать для индекса, а к разобранной строке поиска подмешивать нужные токены из словаря. Второй вариант кажется вполне удачным, если я правильно понял, что в этом случае не придется пересоздавать индексы после пополнения словаря. Поправьте меня, пожалуйста, если я неправ, или может подскажете еще варианты решения.


(Igor Motov) #4

Вы не могли бы описать более подробнее, что вы подразумеваете под

Проблема заключается в поиске русских слов по корню с одним или несколькими суффиксами и окончанием.

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


(Dmitriy Glukhov) #5

Сейчас я частично реализовал второй вариант. Настройки сейчас такие:
"analyzer": {
"ru_search_analyzer": {
"type": "custom",
"filter": [
"lowercase",
"my_stopwords",
"my_synonyms",
"russian_morphology",
"english_morphology"
],
"tokenizer": "standard"
},
"ru_analyzer": {
"filter": [
"lowercase",
"my_stopwords",
"russian_morphology",
"english_morphology"
],
"type": "custom",
"tokenizer": "standard"
}
}
...
"filter": {
"my_synonyms": {
"type": "synonym",
"synonyms" : ["парк => парков"]
}
Т.е. имеем два анализатора - один для индексации, второй для поиска(search_analyzer в маппинге), в котором слово "парк" заменяется на "парков", а далее фильтром морфологии получаем и парк, и парковый - все работает как задумано. Но я столкнулся с проблемой подключения файла словаря в настройках - "synonyms_path": "synonyms.txt" - не подхватывает файл "synonyms.txt" из папки config. В чем может быть проблема? ОС Windows.


(Igor Motov) #6

А что он при этом говорит и пишет в логи?


(Dmitriy Glukhov) #7

В логах:
"... nested: FailedToResolveConfigException[Failed to resolve config path [synonyms.txt], tried file path [synonyms.txt], path file [C:\elasticsearch\config\synonyms.txt], and classpath];"


(Igor Motov) #8

И файл C:\elasticsearch\config\synonyms.txt существует и доступен для чтения? Как вы запускаете elasticsearch и какую версию elasticsearch, Windows и Java вы используете?


(Dmitriy Glukhov) #9

Да, файл конечно существует и доступен, в нем одна строка - "парк => парков". Elasticsearch версии 1.7.0 запускается автоматически как windows service (c:\elasticsearch\bin\elasticsearch-service-x64.exe //RS//elasticsearch-service-x64) под Windows 7 и Java версии 8.45


(Igor Motov) #10

Доступен кому? Вам или пользователю, под которым windows service запущен?


(Dmitriy Glukhov) #11

Всем полный доступ, чтоб наверняка исключить эту причину.


(Igor Motov) #12

Странно. К сожалению, у меня нет под рукой машины с Windows 7 что бы попробовать и посмотреть, что там происходит, но судя по описанию похоже на баг. Завтра на Windows 10 попробую воспроизвести. А вы полный путь к файлу задавать не пробовали?


(Dmitriy Glukhov) #13

Попробовал такой вариант: "synonyms_path" : "C:\elasticsearch\config\synonyms.txt" - индекс вообще не создается с аналогичной ошибкой.


(Igor Motov) #14

У вас сколько машин в кластере? Этот файл присутствует на каждой машине?


(Dmitriy Glukhov) #15

Как я могу узнать сколько машин в кластере? А лучше сразу бы узнать, как ограничить кластер единственной машиной?


(Igor Motov) #16

curl "localhost:9200/_cluster/health?pretty"

Не запускать elasticsearch с тем же именем кластера на других машинах. Либо добавить следующее в elastcisearch.yml.

node.max_local_storage_nodes: 1
network.host: "127.0.0.1"
discovery.zen.ping.unicast.hosts: ["127.0.0.1"]
discovery.zen.ping.multicast.enabled: false

(Dmitriy Glukhov) #17

Добавил указанные вами настройки в elastcisearch.yml - индекс создался без ошибок, в логах нет упоминаний про synonyms.txt, но синонимы из файла все равно не работают, судя по _analyze.


(Igor Motov) #18

А можно на вывод следующих команд посмотреть?

curl localhost:9200/ИМЯ_ИНДЕКСА

и

curl localhost:9200/ИМЯ_ИНДЕКСА/_analyze -d '{
 ... ваш тест анализатора ...
}'

(Dmitriy Glukhov) #19
{
   "opod": {
      "aliases": {},
      "mappings": {
         "ds1465": {
            "_all": {
               "enabled": true,
               "index_analyzer": "ru_analyzer",
               "search_analyzer": "ru_search_analyzer"
            },
            "properties": {
               "Id": {
                  "type": "string"
               },
               "address": {
                  "type": "string",
                  "store": true,
                  "index_analyzer": "ru_analyzer",
                  "search_analyzer": "ru_search_analyzer",
                  "search_quote_analyzer": "ru_analyzer"
               },
               "caption": {
                  "type": "string",
                  "store": true,
                  "index_analyzer": "ru_analyzer",
                  "search_analyzer": "ru_search_analyzer",
                  "search_quote_analyzer": "ru_analyzer"
               }
            }
         }
      },
      "settings": {
         "index": {
            "creation_date": "1459182850853",
            "analysis": {
               "filter": {
                  "my_synonyms": {
                     "type": "synonym",
                     "synonyms_path" : "synonyms.txt"
                  },
                  "my_stopwords": {
                     "type": "stop",
                     "stopwords": "а,без,более,бы ..."
                  }
               },
               "analyzer": {
                  "ru_search_analyzer": {
                     "type": "custom",
                     "filter": [
                        "lowercase",
                        "my_stopwords",
                        "russian_morphology",
                        "english_morphology",
                        "my_synonyms"
                     ],
                     "tokenizer": "standard"
                  },
                  "ru_analyzer": {
                     "filter": [
                        "lowercase",
                        "my_stopwords",
                        "russian_morphology",
                        "english_morphology"
                     ],
                     "type": "custom",
                     "tokenizer": "standard"
                  }
               }
            },
            "number_of_shards": "1",
            "number_of_replicas": "0",
            "version": {
               "created": "1070099"
            },
            "uuid": "tw5CL8QZSqSdFEEGqv93xg"
         }
      },
      "warmers": {}
   }
}

Результат analyze для анализатора ru_search_analyzer по слову "парк":

{
"tokens": [
{
"token": "парк",
"start_offset": 2,
"end_offset": 6,
"type": <ALPHANUM>,
"position": 1
}
]
}

Если в настройках вместо synonyms_path указать
"synonyms": [ "парк => парк, парковый" ]
то анализатор покажет:
{
"tokens": [
{
"token": "парк",
"start_offset": 2,
"end_offset": 6,
"type": "SYNONYM",
"position": 1
},
{
"token": "парковый",
"start_offset": 2,
"end_offset": 6,
"type": "SYNONYM",
"position": 1
}
]
}

В файле соответственно та же строчка: парк => парк, парковый

(Dmitriy Glukhov) #20

Игорь, есть ли какие-то мысли? Возможно, обновление до последней версии поможет?