aws - elasticsearch tutorial
La codificación UTF8 es más larga que la longitud máxima 32766 (10)
Actualicé mi clúster Elasticsearch de 1.1 a 1.2 y tengo errores al indexar una cadena algo grande.
{
"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
}
El mapeo del índice:
{
"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" }
}
}
}
}
He buscado en la documentación y no encontré nada relacionado con un tamaño de campo máximo. De acuerdo con la sección de tipos de núcleo , no entiendo por qué debería "corregir el analizador" para un campo no not_analyzed
.
En Solr v6 + cambié el tipo de campo a text_general y resolvió mi problema.
<field name="body" type="string" indexed="true" stored="true" multiValued="false"/>
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
Entonces te encuentras con un problema con el tamaño máximo para un solo término. Cuando establece un campo para not_analyzed lo tratará como un solo término. El tamaño máximo para un solo término en el índice subyacente de Lucene es 32766 bytes, que creo que está codificado.
Sus dos opciones principales son cambiar el tipo a binario o continuar usando cadena, pero establezca el tipo de índice en "no".
Hay una opción mejor que la que John publicó. Porque con esa solución ya no puedes buscar en el valor.
Volver al problema:
El problema es que, por defecto, los valores de campo se usarán como un único término (cadena completa). Si ese término / cadena es más largo que los 32766 bytes, no se puede almacenar en Lucene.
Las versiones anteriores de Lucene solo registran una advertencia cuando los términos son demasiado largos (e ignoran el valor). Las versiones más recientes arrojan una excepción. Ver corrección de error: https://issues.apache.org/jira/browse/LUCENE-5472
Solución:
La mejor opción es definir un analizador (personalizado) en el campo con el valor de cadena larga. El analizador puede dividir la cadena larga en cadenas / términos más pequeños. Eso solucionará el problema de los términos demasiado largos.
No olvide agregar también un analizador al campo "_all" si está usando esa funcionalidad.
Los analizadores se pueden probar con la API REST. http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/indices-analyze.html
Me encontré con el mismo mensaje de error con el módulo de archivos adjuntos de la API de búsqueda de Drupal:
El documento contiene al menos un término inmenso en el campo = "saa_saa_file_entity" (cuya codificación UTF8 es más larga que la longitud máxima 32766), todos los cuales fueron omitidos. Corrija el analizador para que no produzca dichos términos.
Cambiar los campos de tipo de string
a Fulltext
(en / admin / config / search / search-api / index / elastic_index / fields ) resolvió el problema para mí.
Necesitaba cambiar la parte de index
de la asignación a no
lugar de no not_analyzed
. De esa forma, el valor no está indexado. Permanece disponible en el documento devuelto (de una búsqueda, un get, ...) pero no puedo consultarlo.
Si está utilizando searchkick
, actualice searchkick
a >= 2.2.0
y asegúrese de estar utilizando searchkick 1.3.4
o posterior.
Esta versión de searchkick establece ignore_above = 256
de forma predeterminada, por lo que no obtendrá este error cuando UTF> 32766.
Esto se discute here .
Si realmente quiere que no se not_analyzed
en la propiedad porque quiere hacer un filtrado exacto, puede usar "ignore_above": 256
Aquí hay un ejemplo de cómo lo uso en php:
''mapping'' => [
''type'' => ''multi_field'',
''path'' => ''full'',
''fields'' => [
''{name}'' => [
''type'' => ''string'',
''index'' => ''analyzed'',
''analyzer'' => ''standard'',
],
''raw'' => [
''type'' => ''string'',
''index'' => ''not_analyzed'',
''ignore_above'' => 256,
],
],
],
En su caso, probablemente quiera hacer lo que le dijo John Petrone y establecer "index": "no"
pero para cualquier persona que encuentre esta pregunta después, como yo, buscando esa excepción, sus opciones son:
- establecer
"index": "no"
- establecer
"index": "analyze"
- establecer
"index": "not_analyzed"
e"ignore_above": 256
Depende de si y cómo desea filtrar esa propiedad.
Solucioné este problema cambiando mi analizador.
{
"index" : {
"analysis" : {
"analyzer" : {
"standard" : {
"tokenizer": "standard",
"filter": ["standard", "lowercase", "stop"]
}
}
}
}
}
Una forma de manejar tokens que están por encima del límite de lucene es usar el filtro truncate
. Similar a ignore_above
para palabras clave. Para demostrar, estoy usando 5
. Elasticsearch sugiere usar ignore_above = 32766/4 = 8191
ya que los caracteres UTF-8 pueden ocupar como máximo 4 bytes. 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"
}''
Salida:
{
"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
}
]
}
Usando logstash para indexar esos mensajes largos, utilizo este filtro para truncar la cadena larga:
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
"
}
}
Agrega un campo message_size para que pueda ordenar los mensajes más largos por tamaño.
También agrega la etiqueta de mensaje largo a aquellos que tienen más de 32000kb, por lo que puedo seleccionarlos fácilmente.
No soluciona el problema si tiene la intención de indexar esos mensajes largos por completo, pero si, como yo, no quiere tenerlos en elasticsearch en primer lugar y desea rastrearlos para solucionarlos, es una solución de trabajo.