Как добавить analyser к существующему индексу?


(Igor Gubaidullin) #1

Есть индекс xenf с текстовым полем messages. Я хочу делать текстовый анализ этого поля и пытаюсь прикрутить анализатор примерно вот так:

PUT xenf
{
"settings": {
    "analysis": {
      "filter": {
        "custom_english_stemmer": {
          "type": "stemmer",
          "name": "english"
        }
      },
      "analyzer": {
        "custom_lowercase_stemmed": {
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "custom_english_stemmer"
          ]
        }
      }
    }
  },
  "mappings": {
    "test": {
      "properties": {
        "message": {
          "type": "string",
          "analyzer": "custom_lowercase_stemmed"
        }
      }
    }
  }
} 

При этом получаю ошибку вида

{
  "error": {
    "root_cause": [
      {
        "type": "resource_already_exists_exception",
        "reason": "index [xenf/wG1wAqS-TZ-fLOyj2hE3Aw] already exists",
        "index_uuid": "wG1wAqS-TZ-fLOyj2hE3Aw",
        "index": "xenf"
      }
    ],
    "type": "resource_already_exists_exception",
    "reason": "index [xenf/wG1wAqS-TZ-fLOyj2hE3Aw] already exists",
    "index_uuid": "wG1wAqS-TZ-fLOyj2hE3Aw",
    "index": "xenf"
  },
  "status": 400
}

Я не пойму, как мне сделать анализатор для текстового поля на уже существующем индексе?
Спасибо.


(Vladimir Dolzhenko) #2

Нельзя поменять анализатор к уже существующему индексу и его полю - это связано с тем, что Lucene хранит термы полученные на выходе анализатора.

Что можно сделать так это создать новый индекс с новым анализатором и сделать reindex из старого индекса в новый


(Igor Gubaidullin) #3

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

GET _analyze

выдает ошибку вида

{
  "error": {
    "root_cause": [
      {
        "type": "parse_exception",
        "reason": "request body or source parameter is required"
      }
    ],
    "type": "parse_exception",
    "reason": "request body or source parameter is required"
  },
  "status": 400
}

(Igor Gubaidullin) #4

А такой запрос

POST _analyze
{
  "analyzer": "custom_lowercase_stemmed",
  "text":     "The quick brown fox."
}

выдает

{
  "error": {
    "root_cause": [
      {
        "type": "remote_transport_exception",
        "reason": "[IATGesG][195.214.233.98:9300][indices:admin/analyze[s]]"
      }
    ],
    "type": "illegal_argument_exception",
    "reason": "failed to find global analyzer [custom_lowercase_stemmed]"
  },
  "status": 400
}

(Vladimir Dolzhenko) #5

Такой синтаксис использует глобальный анализатор - и он недоступен по понятным причинам.

Попробуйте использовать анализатор для поля (из приведённого выше вы делали для поля message):

GET index_name/_analyze
{
  "field": "message",
  "text":  "The quick brown fox."
}

где index_name это имя вашего нового индекса (с новым анализатором)


(Igor Gubaidullin) #6

Да, действительно, так работает, спасибо.
Не совсем понятно практическое использование анализатора. Есть поле message, которое постоянно пополняется текстовыми данными. На это поле настроен анализатор. Как получать результаты его работы. Например, из текстов я хотел бы получать ключевые слова, чтобы их видеть в визуализациях Kibana.


(Andrey Ershov) #7

Не совсем понятно, чего вы хотите достичь. Анализатор используется для того, чтобы текстовое поле разбивать на термы. Например, у вас есть строка

Я изучаю ElasticSearch

и вы хотите на выходе получить термы: "я", "изучаю", "ElasticSearch". Для этого можно использовать стандартный анализатор.
Анализатор НЕ предназначен для того, чтобы из текста (или одного поля mapping'a) получать несколько полей. Например, у вас есть лог сообщение

12-Oct-2018 DEBUG Something happened

с помощью анализатора не получиться это сообщение превратить в три поля типа timestamp (для даты), keyword (для уровня логирования) и text (для сообщения). Для этого нужно либо уже отправлять данные в структурированном формате (используя LogStash или Beats) или же использовать Ingestion возможности ElasticSearch.

https://www.elastic.co/guide/en/elasticsearch/reference/master/ingest.html


(Igor Gubaidullin) #8

Да, спасибо. Я ранее использовал Rosette Ingest Pipeline https://github.com/rosette-api/rosette-elasticsearch-plugin/blob/master/docs/Rosette-API-Plugin-for-Elasticsearch-Doc-Enrichment.md для лингво анализа текстового поля. Подключал этот pipeline в разделе output конфига Logstash-а и в индексе Elasticsearch уже имел поля с keywords, sentiments, entities.
Просто подумал, что то же самое можно было бы реализовать встроенным в Elasticsearch анализатором. Вот и пытался разобраться с ним. Но честно говоря, так и не понял, каким способом его можно применять на практике :slight_smile:


(Igor Gubaidullin) #9

Подскажите пожалуйста, как бы можно было решить такую задачу. В поле message есть текст на английском. Я бы хотел дополнительно иметь поле, скажем, words где бы тот же самый текст складывался обработанный английским анализатором stop words, если не ошибаюсь, который бы удалял все слова вида the, from, where, to, a, thanks и так далее из текста из поля messages.
Спасибо.


(Andrey Ershov) #10
  1. Вам нужно добавить новое поле к маппингу, указав для него желаемый analyzer
  2. Используя updateByQuery API скопировать значение поля msg в новое поле https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-update-by-query.html

(Igor Gubaidullin) #11

Спасибо. А вот этот вариант не сработает?

https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html#plugins-filters-mutate-copy


(Andrey Ershov) #12

Я описал, как стоит поступить, если в индексе уже есть данные. Если у вас еще нет индекса, то вам действительно либо нужно посылать два поля в ElasticSearch, либо попробовать воспользоваться https://www.elastic.co/guide/en/elasticsearch/reference/current/copy-to.html.
Если у вас есть в индексе данные и плюс вы хотите продолжить писать в этот индекс, тогда придется сделать и то и другое.


(system) #13

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.