Кодировка UTF8 длиннее максимальной длины 32766

Я обновил свой кластер Elasticsearch с 1.1 до 1.2, и у меня есть ошибки при индексировании несколько большой строки.

{ "error": "IllegalArgumentException[Document contains at least one immense term in field=\"response_body\" (whose UTF8 encoding is longer than the max length 32766), all of which were skipped. Please correct the analyzer to not produce such terms. The prefix of the first immense term is: '[7b 22 58 48 49 5f 48 6f 74 65 6c 41 76 61 69 6c 52 53 22 3a 7b 22 6d 73 67 56 65 72 73 69]...']", "status": 500 } 

Отображение индекса:

 { "template": "partner_requests-*", "settings": { "number_of_shards": 1, "number_of_replicas": 1 }, "mappings": { "request": { "properties": { "asn_id": { "index": "not_analyzed", "type": "string" }, "search_id": { "index": "not_analyzed", "type": "string" }, "partner": { "index": "not_analyzed", "type": "string" }, "start": { "type": "date" }, "duration": { "type": "float" }, "request_method": { "index": "not_analyzed", "type": "string" }, "request_url": { "index": "not_analyzed", "type": "string" }, "request_body": { "index": "not_analyzed", "type": "string" }, "response_status": { "type": "integer" }, "response_body": { "index": "not_analyzed", "type": "string" } } } } } 

Я искал документацию и не нашел ничего, связанного с максимальным размером поля. В соответствии с разделом основных типов я не понимаю, почему я должен «исправить анализатор» для поля not_analyzed .

Таким образом, вы сталкиваетесь с проблемой с максимальным размером для одного термина. Когда вы установите поле not_analyzed, оно будет относиться к нему как к одному термину. Максимальный размер для одного термина в базовом индексе Lucene составляет 32766 байт, что, я считаю, жестко закодировано.

Два основных параметра – либо изменить тип на двоичный, либо продолжить использование строки, но установить тип индекса «нет».

Если вы действительно хотите not_analyzed на свойство, потому что вы хотите сделать точную фильтрацию, вы можете использовать "ignore_above": 256

Вот пример того, как я использую его в php:

 'mapping' => [ 'type' => 'multi_field', 'path' => 'full', 'fields' => [ '{name}' => [ 'type' => 'string', 'index' => 'analyzed', 'analyzer' => 'standard', ], 'raw' => [ 'type' => 'string', 'index' => 'not_analyzed', 'ignore_above' => 256, ], ], ], 

В вашем случае вы, вероятно, захотите сделать так, как сказал вам Джон Петреон и установили "index": "no" но для тех, кто еще нашел этот вопрос после того, как я, как и я, выполнив поиск по этому Исключению, ваши варианты:

  • set "index": "no"
  • установить "index": "analyze"
  • установите "index": "not_analyzed" и "ignore_above": 256

Это зависит от того, как и как вы хотите фильтровать это свойство.

Существует лучший вариант, чем тот, который опубликовал Джон. Потому что с этим решением вы больше не можете искать значение.

Вернуться к проблеме:

Проблема в том, что значения полей по умолчанию будут использоваться как один термин (полная строка). Если этот термин / строка длиннее 32766 байт, он не может быть сохранен в Lucene.

Более старые версии Lucene регистрируют предупреждение только в том случае, если условия слишком длинные (и игнорируют значение). Новые версии выбрасывают исключение. См. Исправление: https://issues.apache.org/jira/browse/LUCENE-5472

Решение:

Лучшим вариантом является определение (пользовательский) анализатор в поле с длинным строковым значением. Анализатор может разделить длинную строку на более мелкие строки / термины. Это решит проблему слишком длинных сроков.

Не забудьте также добавить анализатор в поле «_all», если вы используете эту функцию.

Анализаторы могут быть протестированы с помощью REST api. http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-analyze.html

Мне нужно было изменить index часть отображения на no вместо not_analyzed . Таким образом, значение не индексируется. Он остается доступным в возвращаемом документе (из поиска, get, …), но я не могу его запросить.

Один из способов обработки токенов, которые превышают линус, – использовать фильтр truncate . Подобно ignore_above для ключевых слов. Чтобы продемонстрировать, я использую 5 . Elasticsearch предлагает использовать ignore_above = 32766/4 = 8191 поскольку символы UTF-8 могут занимать не более 4 байт. https://www.elastic.co/guide/en/elasticsearch/reference/6.3/ignore-above.html

 curl -H'Content-Type:application/json' localhost:9200/_analyze -d'{ "filter" : [{"type": "truncate", "length": 5}], "tokenizer": { "type": "pattern" }, "text": "This movie \n= AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" }' 

Вывод:

 { "tokens": [ { "token": "This", "start_offset": 0, "end_offset": 4, "type": "word", "position": 0 }, { "token": "movie", "start_offset": 5, "end_offset": 10, "type": "word", "position": 1 }, { "token": "AAAAA", "start_offset": 14, "end_offset": 52, "type": "word", "position": 2 } ] } 

Я столкнулся с этой проблемой, изменив свой анализатор.

 { "index" : { "analysis" : { "analyzer" : { "standard" : { "tokenizer": "standard", "filter": ["standard", "lowercase", "stop"] } } } } } 

Если вы используете searchkick , обновите elasticsearch до >= 2.2.0 и убедитесь, что используете searchkick 1.3.4 или новее.

Эта версия searchkick устанавливает ignore_above = 256 по умолчанию, поэтому вы не получите эту ошибку, когда UTF> 32766.

Это обсуждается здесь .

В Solr v6 + я изменил тип поля на text_general, и он решил мою проблему.

   

Используя logstash для индексации этих длинных сообщений, я использую этот фильтр для усечения длинной строки:

  filter { ruby { code => "event.set('message_size',event.get('message').bytesize) if event.get('message')" } ruby { code => " if (event.get('message_size')) event.set('message', event.get('message')[0..9999]) if event.get('message_size') > 32000 event.tag 'long message' if event.get('message_size') > 32000 end " } } 

Он добавляет поле message_size, чтобы я мог сортировать самые длинные сообщения по размеру.

Он также добавляет длинный тег сообщения тем, которые превышают 32000 КБ, поэтому я могу их легко выбрать.

Это не решит проблему, если вы намерены полностью индексировать эти длинные сообщения, но если, как и я, вы не хотите, чтобы они были в elasticsearch в первую очередь и хотите отслеживать их, чтобы исправить это, это рабочее решение.

Я наткнулся на то же сообщение об ошибке с модулем вложений приложения api для Drupal:

Документ содержит по крайней мере один огромный термин в поле = «saa_saa_file_entity» (чье кодирование UTF8 длиннее максимальной длины 32766), все из которых были пропущены. Пожалуйста, исправьте анализатор, чтобы не создавать такие термины.

Изменение типа полей из string в Fulltext/ admin / config / search / search-api / index / elastic_index / fields ) решило проблему для меня.

  • Поиск имени файла с помощью ElasticSearch
  • Как проиндексировать PDF-файл в Elasticsearch 5.0.0 с помощью плагина ingest-attachment?
  • Как нечеткое соответствие электронной почте или телефону Elasticsearch?
  • есть ли способ десериализации поискового запроса Elasticsearch Nest?
  • Как найти часть слова с помощью ElasticSearch
  • Как не анализировать в ElasticSearch?
  • Расчет времени между событиями
  • Максимальное ограничение на количество значений, которые я могу указать в фильтре идентификаторов или в общем случае запроса?
  • Elasticearch 2.1: окно результатов слишком велико (index.max_result_window)
  • Импортировать / индексировать файл JSON в Elasticsearch
  • ElasticSearch, Sphinx, Lucene, Solr, Xapian. Что подходит для использования?
  • Давайте будем гением компьютера.