Кодировка 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" }
      }
    }
  }
}

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

10 53

10 ответов:

таким образом, вы столкнулись с проблемой с максимальным размером для одного термина. Когда вы устанавливаете поле 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"
  • set "index": "analyze"
  • set "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,...), но я не могу запросить его.

один из способов обработки токенов, которые превышают предел lucene, заключается в использовании 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, и это решило мою проблему.

<field name="body" type="string" indexed="true" stored="true" multiValued="false"/>   
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>

используя 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 поле, так что я могу сортировать самые длинные сообщения по размеру.

Он также добавляет долго тег для тех, которые находятся над 32000kb, так что я могу выбрать их легко.

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

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

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

изменение типа полей с string до Fulltext (in /администратором/настройка/поиск/поиск-АПИ/индекс/elastic_index/поля) решил проблему для меня.