Анализатор английского языка (стемминг) в ElasticSearch не работает

Я попытался применить собственный анализатор английского языка, а также стандартный анализатор английского языка в elasticsearch. Моя цель - особенно использовать стемминг. Допустим, у меня в документах есть следующие слова: обложки, оттиски.

Теперь, если я буду искать, например, обложка или впечатляющая или впечатления, я получаю 0 результатов. Только если я буду искать точные термины «покрывает» или «впечатление», я найду результаты.

Это мои настройки в elasticsearch (согласно этой документации https://www.elastic.co/guide/en/elasticsearch/reference/current/analysis-lang-analyzer.html):

{
  "settings": {
    "analysis": {
      "filter": {
        "english_stop": {
          "type":       "stop",
          "stopwords":  "_english_" 
        },
        "english_stemmer": {
          "type":       "stemmer",
          "language":   "english"
        },
        "english_possessive_stemmer": {
          "type":       "stemmer",
          "language":   "possessive_english"
        }
      },
      "analyzer": {
        "rebuilt_english": {
          "tokenizer":  "standard",
          "filter": [
            "english_possessive_stemmer",
            "lowercase",
            "english_stop",
            "english_stemmer"
          ]
        }
      }
    }
  }
}

Мое отображение выглядит следующим образом:

"mapping": {
  "_doc": {
     "properties": {
        "title": {"type": "text",
                   "analyzer": "rebuilt_english"},
        "description: {"type": text"
                       "analyzer": "rebuilt_english"}
  }
 }
}

Я также попытался (согласно нескольким различным руководствам) изменить такие настройки (я просто добавляю здесь изменения, а не снова полный код):

{
  "settings": {
    "analysis": {
    "analyzer: "rebuilt_english" {
    "type": "custom",
     "filter": #and so on...

Я что-то здесь упускаю? Насколько я понимаю, мне нужно установить настройки для конкретного анализатора в «настройках», дать ему имя, а затем использовать это имя в свойствах «сопоставления», чтобы каждый элемент анализировался в соответствии с настройками, установленными выше.

Я также старался не устанавливать какие-либо конкретные настройки и просто задавал свойства анализатора (в сопоставлении) для каждого элемента, например:

"title": {"type": "text",
"analyzer": "english"}

Что также не работает (даже при использовании таких фильтров, как стемминг).

Я действительно часами пытался найти решение, но не могу заставить его работать. Помощь будет очень признательна. Спасибо!

ОБНОВЛЕНИЕ

Это код, который я использовал для создания индекса (моя последняя попытка, согласно моему описанию, я также пробовал другие способы применения метода):

PUT /my_index

{
  "settings": {
    "analysis": {
      "analyzer": {
        "rebuilt_english": {
          "type": "custom",
      "filter": {
        "english_stop": {
          "type": "stop",
          "stopwords": "_english"
        },
        "english_stemmer": {
          "type": "stemmer",
          "language": "english"
        },
        "english_possessive_stemmer": {
          "type": "stemmer",
          "language": "possessive_english"
        },
          "tokenizer": "standard",
          "filter": [
            "english_possessive_stemmer",
            "lowercase",
            "english_stop",
            "english_stemmer"
            ]
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "title": { "type": "text",
          "analyzer": "rebuilt_english"
        },
        "description": { "type": "text",
                    "analyzer": "rebuilt_english"}
                    }
        }
      }
    }
}

person runner2018    schedule 24.01.2019    source источник
comment
Можете ли вы опубликовать фактическое сопоставление индексов? GET /index-name должен вернуть это. Может где-то была ошибка   -  person Evaldas Buinauskas    schedule 24.01.2019
comment
Когда я это делаю, я на самом деле замечаю, что с моими элементами не сопоставлен никакой анализатор, хотя я сопоставил анализатор при создании своего индекса. Правильно отображается только тип.   -  person runner2018    schedule 24.01.2019
comment
Вот и все. Я думаю, проблема в том, что вы указали mappping, а не mappings при создании индекса.   -  person Evaldas Buinauskas    schedule 24.01.2019
comment
Я проверил и фактически использовал mappings.   -  person runner2018    schedule 24.01.2019
comment
Я обновлю свой вопрос и опубликую код, который я использовал для создания индекса, в конце своего сообщения.   -  person runner2018    schedule 24.01.2019


Ответы (3)


Ваша проблема заключалась в том, что у вас был ключ filter, где все ваши именованные фильтры были в неправильном месте. Он был помещен в analyzer, но должен был быть ключом-братом для analyzer.

Поэтому я уверен, что следующая конфигурация должна работать должным образом:

{
  "settings":{
    "analysis":{
      "filter":{
        "english_stop":{
          "type":"stop",
          "stopwords":"_english"
        },
        "english_stemmer":{
          "type":"stemmer",
          "language":"english"
        },
        "english_possessive_stemmer":{
          "type":"stemmer",
          "language":"possessive_english"
        }
      },
      "analyzer":{
        "rebuilt_english":{
          "type":"custom",
          "tokenizer":"standard",
          "filter":[
            "english_possessive_stemmer",
            "lowercase",
            "english_stop",
            "english_stemmer"
          ]
        }
      }
    },
    "mappings":{
      "_doc":{
        "properties":{
          "title":{
            "type":"text",
            "analyzer":"rebuilt_english"
          },
          "description":{
            "type":"text",
            "analyzer":"rebuilt_english"
          }
        }
      }
    }
  }
}
person Evaldas Buinauskas    schedule 24.01.2019
comment
Я действительно ценю твою помощь. Но я попробовал код, который вы опубликовали раньше (и теперь снова), и он все еще не работает для меня. Вот почему я возился со своим кодом, пытаясь делать разные вещи. У меня есть слово «балансировка» в документе, но когда я пытаюсь найти баланс, я все равно не получаю совпадений. Я действительно заблудился. Поскольку я считаю, что отображение и настройки правильные (согласно вашему ответу), мне придется найти Гремлина в другом месте :). - person runner2018; 24.01.2019
comment
Вы пробовали тестировать свои анализаторы? т.е. GET my_index/_analyze {"analyzer":"rebuilt_english","text":"balancing"}, а затем сравнивая его с GET my_index/_analyze {"analyzer":"rebuilt_english","text":"balance"} Может быть, ваши ожидания скорее предположения? - person Evaldas Buinauskas; 24.01.2019
comment
Спасибо за подсказку. Я попробовал и на самом деле получил ошибку: не удалось найти анализатор [rebuilt_english]. Это имеет смысл, поскольку я не вижу никакого анализатора, сопоставленного с моими элементами, когда набираю GET my_index. Однако мне удалось сопоставить rebuilt_english с элементами при создании индекса. НО ЗАТЕМ СЛЕДУЮЩАЯ ПРОБЛЕМА: я использую scrapy и отправляю свои очищенные данные через конвейер в elasticsearch. Это работает как шарм. Но всякий раз, когда я применял английский фильтр к своим элементам, данные не поступают в elasticsearch после очистки. Мой индекс остается пустым. Возможно, мне нужно будет задать другой вопрос. - person runner2018; 24.01.2019
comment
Чтобы закрыть эту тему: я считаю, что дьявол был недостающей скобкой. Перед отображениями необходимо вставить закрывающую скобку }. Вместо этого пришлось удалить закрывающую скобку в конце скрипта. После этого сопоставление rebuilt_english было успешно применено. - person runner2018; 24.01.2019
comment
Тем не менее, я не понимаю, почему данные из scrapy больше не проходят через конвейер только потому, что я применил анализатор. Я думал, что анализатор не имеет отношения к индексному процессу. - person runner2018; 24.01.2019
comment
Вполне возможно, что ваш инструмент пытается отправить данные в другой тип, чем в index. Elasticsearch версии 6 поддерживает только один тип, а в вашем случае его _doc, и это может быть одной из причин. Он может попытаться отправить документ другого типа и потерпит неудачу. - person Evaldas Buinauskas; 24.01.2019
comment
Я бы также проверил журналы elasticsearch. Вы должны найти точную информацию о том, почему индексирование не удается. - person Evaldas Buinauskas; 24.01.2019

PUT /my_index
{
  "settings": {
    "analysis": {
      "analyzer": {
        "english_stop": {
          "type":"standard",
          "stopwords": "_english_"
          },
          "my_analyzer": {
            "type":"custom",
            "tokenizer":"standard",
            "filter":["my_stemmer"]
          }
        },
        "filter": {
          "my_stemmer":{
            "type": "stemmer",
            "language": "english"
          }
        }
    }
  }
}

POST /my_index/_analyze
{
  "analyzer": "my_analyzer",
  "text": "I'm in the mood for drinking semi-dry wine!"
}

Думаю, это поможет. Спасибо.

person emon    schedule 11.04.2019

Этот анализатор ниже будет работать, исправление - пока вы определили "tokenizer":"standard", тогда не определяйте поле "type":"standard"

PUT /analyzers_test
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "standard",
          "filter": [
            "my_stemmer",
            "lowercase"
          ]
        }
      },
      "filter": {
        "my_stemmer": {
          "type": "stemmer",
          "name": "english"
        }
      }
    }
  }
}
person Akoffice    schedule 17.09.2019