2015-03-09 9 views
2

Я хранил комментарии Facebook в Elasticsearch 1.4.4. Хотя индексация, я получаю иногда сообщения об ошибках от Elasticsearch об огромных условиях:Удалить длинные юникодные термины из String в Java

java.lang.IllegalArgumentException: Document contains at least one immense term 
in field="message" (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: '[-40, -75, -39, -124, -39, -118, 32, -40, -89, -39, -124, -39, -124, -39, -121, 32, -40, -71, -39, -124, -39, -118, -39, -121, 32, -39, -120, -40, -77, -39]...', original message: bytes can be at most 32766 in length; got 40986 

Причина должна быть, что некоторые UTF8-члены больше, чем 32766 байт (смотри также this SO-question).

Я хочу обнаружить эти сообщения и пропустить их для индексирования или дезинфекции слишком больших сообщений ввода. Поэтому я попытался проверить размер байта сбойными строками, закодированными в UTF8. Но часто это намного ниже, чем волшебный 32766 предел байт, f.ex .:

String failingMessage = "ﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺﷺ"; 
failingMessage.getBytes(StandardCharsets.UTF_8).length == 3728 

Так как я могу предотвратить Elasticsearch бросить IllegalArgumentExceptions на этот вход? Есть ли хороший способ дезинфицировать UTF8-Text для этого типа длительных сроков? Является ли мой метод привязки строк к байту неправильным? (Long, Полезные комментарии очень редко на Facebook, так что это не имеет значения, если я пропущу все слишком длинный текст)

Анализатор Elasticsearch я индексировать message поле:

  "en_analyzer": { 
       "type": "custom", 
       "tokenizer": "icu_tokenizer", 
       "filter": ["icu_folding", "icu_normalizer", "en_stop_filter", "en_stem_filter"] 
      }, 
+3

Я храню вопросы о переполнении стека в Elasticsearch 1.4.4. Я нашел ваш вопрос, потому что теперь наш Elasticsearch выдает ту же ошибку (из-за сообщения об ошибке, которое вы предоставили). Как это круто? – Jacket

+0

* rofl * Я не знал, насколько опасен мой вопрос. – Sonson123

+0

Странно, что ваш термин длится 3726 байт, но наш экземпляр ES тоже не может его поглотить. И поскольку мы останавливаемся при каждой ошибке, теперь наше полное индексирование остановилось.Я попытаюсь найти ответ на вопрос после того, как мы исправим наши операции :) – Jacket

ответ

1

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

Я знаю, что это своего рода хромая работа, вокруг, но, по крайней мере, он не убивает всего индексатора.

Перед (функция PHP с помощью elasticsearch-php):

function elastic_bulk_operation($params){ 
    if(count($params) == 0){ 
     return true; 
    } 
    try{ 
     $client = new Elasticsearch\Client(['host' => ELASTIC_SEARCH_HOST]); 
     $result = $client->bulk($params); 
     foreach($result['items'] as $item){ 
      if($item['index']['error']){ 
       return false; 
      } 
     } 
     return true; 
    }catch(Exception $e){ 
     return false; 
    } 
    return true; 
} 

Сейчас:

function elastic_bulk_operation($params){ 
    if(count($params) == 0){ 
     return true; 
    } 
    try{ 
     $client = new Elasticsearch\Client(['host' => ELASTIC_SEARCH_HOST]); 
     $result = $client->bulk($params); 
     foreach($result['items'] as $item){ 
      if($item['index']['error'] && strpos($item['index']['error'],"Document contains at least one immense term") === false){ 
       return false; 
      } 
     } 
     return true; 
    }catch(Exception $e){ 
     if(strpos($e->getMessage(),"Document contains at least one immense term") === false){ 
      return false; 
     } 
    } 
    return true; 
} 
+0

Thanx для обмена кодом. (Кстати, я надеюсь, что Elasticsearch улучшит обработку ошибок в будущем, а сравнение исключений - боль.) – Sonson123

1

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

Наш искатель нашел эту страницу, извлек текст, проверил, что он не длиннее 32766 байт, но получил то же сообщение об ошибке при попытке индексации документа в elasticsearch.

По-видимому, причина в том, что у нас есть фильтры icu_normalizer и icu_folding в анализаторе для поля, в котором хранится содержимое страницы. Оба этих фильтра расширяют лигулярные символы Unicode, и, к сожалению, лигуратура из вопроса U + FDFA ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM расширяется до строки, состоящей из 33 байтов: «صلي الله عليه وسلم», в результате чего маркер длины 33 * 1242 = 40986 байтов! Следующий вызов _analyze подтверждает это:

$ curl '127.0.0.1:9200/_analyze' -d '{"tokenizer":"keyword","token_filters":["icu_folding"],"text":"ﷺ"}' 
{"tokens":[{"token":"صلي الله عليه وسلم","start_offset":0,"end_offset":1,"type":"word","position":0}]} 

Теперь мы решили его заменить лигатуры U + FDFA с предполагаемым текстом, но есть много других лигатур, которые должны быть обработаны, а также (например, «FFI» = > «ffi»), только U + FDFA расширяется до такой длинной строки, что она была поймана первой.