Кодировка 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
.
- Изменение отображения по умолчанию для строки «не анализировано» в Elasticsearch
- Запросы против фильтров
- Как использовать Elasticsearch с MongoDB?
- ES продолжает возвращать каждый документ
- Как изменить максимальный размер памяти Elasticsearch
- Как получить уникальный счетчик поля с помощью Kibana + Elastic Search
- Репликация Elasticsearch других системных данных?
- Удаление дубликатов документов из поиска в Elasticsearch
- ElasticSearch - возвращает уникальные значения
- FIELDDATA Данные слишком велики
- Запрос Elasticsearch для возврата всех записей
- Осколки и реплики в Elasticsearch
- Сделать elasticsearch только возвращать определенные поля?
Таким образом, вы сталкиваетесь с проблемой с максимальным размером для одного термина. Когда вы установите поле 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 ) решило проблему для меня.