Транслит/Фонетика


(Ilya Shipilov) #1

Задача построить такой индекс, который бы успешно находил запись "Johnson's Baby" по запросам "Джонсон с бэби", "Жонсон бэйби".

Мне кажется, что правильно использовать фильтр фонетики, с поддержкой английского и русского языков, чтобы в индексе хранилась некая универсальная транскрипция.

 "filter" : {
            "beider_morse": {
                "type" : "phonetic",
                "encoder" : "beider_morse",
                "languageset" : [ "russian", "cyrillic", "english" ]
            }
         },
   "analyzer" : {
            "phoneticAnalyzer" : {
                "type" : "custom",
                "tokenizer" : "standard",
                "filter" : ["standard", "lowercase", "beider_morse"]
            }
         }

Латиница фильтруется:

GET /my_index/_analyze?analyzer=phoneticAnalyzer
{
    "text": "Johnson"
}

выдает токены: ionzon, zonzon, а для кириллицы результата нет:

GET /my_index/_analyze?analyzer=phoneticAnalyzer
{
    "text": "Джонсон"
}

выдает только "джонсон".

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


(Igor Motov) #2

Это сложная проблема. Единственное хорошее решение, которое я видел базировалось на машинном обучении. Транслитерация сама по себе не сложна - см тут https://www.elastic.co/guide/en/elasticsearch/plugins/2.4/analysis-icu-transform.html Но, когда дело доходит до имен - большое количество исключений и исторически сложившихся написаний все портит.


(Ilya Shipilov) #3

Игорь, на самом деле у меня вопрос наверное даже проще.

Наши документы это наименования товаров, люди вводят вместо "Johnson's baby", "micro sd" "жонсонов с бэби" и прочее.

Думаю, для нашей задачи попробовать phonetic-filter можно, вот результаты вывода
org.apache.commons.codec.language.bm.BeiderMorseEncoder#encode (его использует алгоритм beider_morse) для некоторых вариантов из топа наших запросов:

тачскрин: tatskrn|totskrn
touchscreen: DtskrDn|tDtskrn|tDxskrDn|tDxskrn|tDxstzrn|taxskrn|totskrDn|totskrn|toxskrDn|toxskrn|toxstzrn|tutskrDn|tutskrn|tuxskrDn|tuxskrn|tuxstzrn

Intersection: [totskrn]

johnson: ionzon|ionzun|xonzon|zonzon
джонсон: zinzon|zonzon
жонсон: zinzon|zonzon

Intersection: [zonzon]

Т.е. оно работает, но проблема когда я выполняю индексацию в elastic, русские слова фильтр не обрабатывает (конфиг в предыдущем посте).


(Igor Motov) #4

Я думаю, что это происходит из-за russian в списке языков. Судя по списку правил, russian работает с русскими фамилиями, написанными латиницей.

В то время как, cyrillic содержит правила с транслитерацией


(Ilya Shipilov) #5

Да, верно, тоже подебажил и обнаружил это, с cyrillic заработало.

Плюс, я неправильно использовал параметр languageset - если задать "cyrillic, english" то фильтроваться будут либо только латинские, либо только кириллические токены, весьма неочевидная оказалась для меня настройка.. Решил двумя фильтрами:

"analyzer": {
  "my_analyzer": {
    "tokenizer": "standard",
    "filter": [
      "standard",
      "my_phonetic_english",
      "my_phonetic_cyrillic"
    ]
  }
},
"filter": {
  "my_phonetic_cyrillic": {
    "type": "phonetic",
    "encoder": "beider_morse",
    "rule_type" : "approx",
    "name_type" : "generic",
    "languageset" : ["cyrillic"]
  },
  "my_phonetic_english": {
    "type": "phonetic",
    "encoder": "beider_morse",
    "rule_type" : "approx",
    "name_type" : "generic",
    "languageset" : ["english"]
  }

(Ilya Shipilov) #6

Единственное хорошее решение, которое я видел базировалось на машинном обучении

Любопытно. А нет возможности тоже познакомиться с этим решением?


(Igor Motov) #7

http://www.basistech.com/text-analytics/rosette/name-translator/


(system) #8