Bienvenido, les saluda Luis y aquí les traigo este post.
Índice
Las diferencias entre ellos y cómo se comportan
Mucha gente que acaba de comenzar a aprender Elasticsearch a menudo confunde el tipo de datos de campo Text
y Keyword
. La diferencia entre ellos es simple, pero muy crucial.
En este artículo, hablaré sobre la diferencia, cómo usarlos, cómo se comportan y cuál usar entre los dos.
Las diferencias
La diferencia crucial entre ellos es que Elasticsearch analizará el Text
antes de que se almacene en el índice invertido, mientras que no analizará el tipo Keyword
. Analizado o no analizado afectará cómo se comportará al recibir una consulta.
Si recién está comenzando a aprender Elasticsearch y aún no sabe qué es Inverted Index and Analyzer, le recomiendo leer primero una guía básica de Elasticsearch .
Cómo usarlos
Si indexa un documento en Elasticsearch que contiene una cadena sin definir la asignación a los campos antes, Elasticsearch creará una asignación dinámica con ambos tipos de datos Text
y Keyword
.
Pero incluso si funciona con mapeo dinámico, le sugiero que defina una configuración de mapeo antes de indexar cualquier documento según el caso de uso para ahorrar espacio y aumentar la velocidad de escritura.
Estos son ejemplos de la configuración de mapeo para Text
y tipo Keyword
, tenga en cuenta que usaré un índice llamado “texto-vs-palabra clave” que he creado antes para este ejemplo.
curl --request PUT \
--url http://localhost:9200/text-vs-keyword/_mapping\
--header 'content-type: application/json' \
--data '{
"properties": {
"keyword_field": {
"type": "keyword"
}
}
}'
curl --request PUT \
--url http://localhost:9200/text-vs-keyword/_mapping \
--header 'content-type: application/json' \
--data '{
"properties": {
"text_field": {
"type": "text"
}
}
}'
curl --request PUT \
--url http://localhost:9200/text-vs-keyword/_mapping \
--header 'content-type: application/json' \
--data '{
"properties": {
"text_and_keyword_mapping": {
"type": "text",
"fields": {
"keyword_type": {
"type":"keyword"
}
}
}
}
}'
Cómo trabajan ellos
Ambos tipos de campo se indexan de manera diferente en el índice invertido. La diferencia en el proceso de indexación afectará cuando realice una consulta en Elasticsearch.
Indexemos un documento por ejemplo:
curl --request POST \
--url http://localhost:9200/text-vs-keyword/_doc/example \
--header 'content-type: application/json' \
--data '{
"keyword_field":"The quick brown fox jumps over the lazy dog",
"text_field":"The quick brown fox jumps over the lazy dog"
}'
Después de ejecutar el comando curl
anterior, si obtiene todos los documentos en el índice, debería tener:
[ { "_index": "text-vs-keyword", "_type": "_doc", "_id": "example", "_score": 1.0, "_source": { "keyword_field": "The quick brown fox jumps over the lazy dog", "text_field": "The quick brown fox jumps over the lazy dog" } } ]
Vamos a empezar con el más simple, Keyword
. Elasticsearch no analizará los tipos de datos Keyword
, lo que significa que la cadena que indexa permanecerá como está.
Entonces, con el ejemplo anterior, ¿cómo se vería la cadena en el índice invertido?
Sí, tienes razón, es exactamente como escribes.
A diferencia del tipo de datos de campo Keyword
, la cadena indexada a Elasticsearch pasará por el proceso del analizador antes de almacenarse en el índice invertido.
De forma predeterminada, el analizador estándar de Elasticsearch dividirá y reducirá la cadena que indexamos. Puede obtener más información sobre el analizador estándar en la documentación de Elasticsearch.
Elasticsearch tiene una API para comprobar cómo quedaría el texto tras el proceso de análisis de su programación, podemos probarlo con:
curl --request POST \
--url http://localhost:9200/text-vs-keyword/_analyze?pretty \
--header 'content-type: application/json' \
--data '{
"analyzer": "standard",
"text": "The quick brown fox jumps over the lazy dog"
}'
Entonces, de acuerdo con la respuesta anterior, así es como debería verse el índice invertido para el campo text_field
.
Solo un poco diferente al anterior keyword
, ¿verdad? Pero debe prestar atención a lo que almacena en el índice invertido porque afectará principalmente al proceso de consulta.
Consulta de texto y palabra clave
Ahora que entendemos como text
y keyword
se comportan cuando se indexan, aprendamos cómo se comportan cuando se les consulta.
Primero, debemos saber que hay dos tipos de consultas para la cadena:
- Consulta de coincidencias.
- Consulta de término.
Igual que Text
y Keyword
, la diferencia entre Match Query
y Term Query
es que la consulta en Match Query
primero se analizará en términos, mientras que la consulta en Term Query
no lo hará.
La consulta de Elasticsearch funciona al hacer coincidir los términos consultados con los términos del índice invertido, los términos consultados y el del índice invertido deben ser exactamente iguales; de lo contrario, no coincidirán.
Esto significa que la cadena analizada y la cadena no analizada en los resultados de indexación y consulta producirán un resultado muy diferente.
Debido a que tanto el tipo de datos de campo como la consulta no se analizan, ambos deberán ser exactamente iguales para que puedan producir un resultado.
Si intentamos con la misma consulta exacta:
curl --request POST \
--url 'http://localhost:9200/text-vs-keyword/_doc/_search?size=0' \
--header 'content-type: application/json' \
--data '{
"query": {
"term": {
"keyword_field": "The quick brown fox jumps over the lazy dog"
}
}
}'
Elasticsearch devolverá un resultado:
{ "_index": "text-vs-keyword", "_type": "_doc", "_id": "example", "_score": 0.2876821, "_source": { "keyword_field": "The quick brown fox jumps over the lazy dog", "text_field": "The quick brown fox jumps over the lazy dog" } } }
Si intentamos con algo que no es exacto, incluso si existe la palabra en el índice invertido:
curl --request POST \
--url 'http://localhost:9200/text-vs-keyword/_doc/_search?size=0' \
--header 'content-type: application/json' \
--data '{
"query": {
"term": {
"keyword_field": "The"
}
}
}'
No devolvió ningún resultado porque el término de la consulta no coincide con ninguno de los términos del índice invertido.
Primero intentemos consultar la misma cadena «El rápido zorro marrón salta sobre el perro perezoso» con Match Query
a keyword_mapping
y mira lo que pasa:
curl --request POST \
--url http://localhost:9200/text-vs-keyword/_doc/_search \
--header 'content-type: application/json' \
--data '{
"query": {
"match": {
"keyword_field": "The quick brown fox jumps over the lazy dog"
}
}
}'
El resultado debería ser:
{ "_index": "text-vs-keyword", "_type": "_doc", "_id": "example", "_score": 0.2876821, "_source": { "keyword_field": "The quick brown fox jumps over the lazy dog", "text_field": "The quick brown fox jumps over the lazy dog" } }
Espere, no debería producir ningún resultado porque los términos producidos en la consulta analizada no coinciden exactamente con el «El rápido zorro marrón salta sobre el perro perezoso» en el Índice invertido, pero ¿por qué produce un resultado?
Así es, la consulta se analizó porque estamos usando Match Query
, pero en lugar de un analizador estándar, Elasticsearch utilizó el analizador index-time
, que se asignó al tipo de datos de campo Keyword
.
Dado que el analizador se asignó con el tipo de datos del campo Keyword
es Term Analyzer, Elasticsearch no cambió nada en la consulta.
Ahora, probemos con un analizador estándar:
curl --request POST \
--url http://localhost:9200/text-vs-keyword/_doc/_search \
--header 'content-type: application/json' \
--data '{
"query": {
"match": {
"keyword_field": {
"query": "The quick brown fox jumps over the lazy dog",
"analyzer":"standard"
}
}
}
}'
No se produce ningún resultado porque analiza la consulta en términos y nada es una coincidencia exacta con el término en el índice invertido.
Consultando el tipo de texto con Term Query
El documento indexado de tipo texto tendrá muchos términos como podemos ver en el apartado anterior. Para mostrar cómo la consulta se empareja con los términos en el índice invertido, intentemos dos consultas.
La primera consulta envía la oración completa a Elasticsearch;
curl --request POST \
--url 'http://localhost:9200/text-vs-keyword/_doc/_search?pretty=' \
--header 'content-type: application/json' \
--data '{
"query": {
"term": {
"text_field": "The quick brown fox jumps over the lazy dog"
}
}
}'
El segundo solo "The"
.
curl --request POST \
--url 'http://localhost:9200/text-vs-keyword/_doc/_search?pretty=' \
--header 'content-type: application/json' \
--data '{
"query": {
"term": {
"text_field": "The"
}
}
}'
Ambas consultas no producen ningún resultado.
La primera consulta no produjo ningún resultado porque, en el índice invertido, nunca almacenamos la oración completa, el proceso de indexación solo almacena los términos que ya se han fragmentado del texto.
La segunda consulta tampoco produjo ningún resultado. Hay un "The"
en el documento indexado, pero recuerde que el analizador redujo la palabra en minúsculas, por lo que en el índice invertido, se almacena como "the"
.
Probemos de nuevo la Consulta de términos con "the"
:
curl --request POST \
--url 'http://localhost:9200/text-vs-keyword/_doc/_search?pretty=' \
--header 'content-type: application/json' \
--data '{
"query": {
"term": {
"text_field": "the"
}
}
}'
¡Sí! produjo un resultado porque la consulta "the"
es una coincidencia exacta con el "the"
en el índice invertido.
Consultar tipo de texto con una consulta de coincidencia
Ahora es el momento de escribir texto con Match Query
, dado que analiza ambos tipos, es fácil hacer que produzcan resultados. Probemos con dos consultas primero
La primera consulta enviará "The"
al Elasticsearch, sabemos que con term query
no produce ningún resultado, pero ¿qué pasa con match query
?
La segunda consulta enviará «el perro LAZ
tropezó con el perro marrón RÁPIDO
«, algunas palabras están en el índice invertido, otras no, ¿producirá Elasticsearch algún resultado?
curl --request POST \ --url 'http://localhost:9200/text-vs-keyword/_doc/_search?pretty=' \ --header 'content-type: application/json' \ --data '{ "query": { "match": { "text_field": "The" } } }'curl --request POST \ --url 'http://localhost:9200/text-vs-keyword/_doc/_search?pretty=' \ --header 'content-type: application/json' \ --data '{ "query": { "match": { "text_field": "the LAZ dog tripped over th QUICK brown dog" } } }'
¡Sí! Ambos produjeron un resultado.
{ "_index": "text-vs-keyword", "_type": "_doc", "_id": "example", "_score": 0.39556286, "_source": { "keyword_field": "The quick brown fox jumps over the lazy dog", "text_field": "The quick brown fox jumps over the lazy dog" } }
La primera consulta produjo un resultado porque se analizó "The"
en la consulta y se convirtió en "the"
, que es la coincidencia exacta con la del índice invertido.
La segunda consulta, aunque no todos los términos están en el índice invertido, todavía produce un resultado. Elasticsearch devolverá un resultado, incluso si solo uno de los términos consultados coincide exactamente con el del índice invertido.
Si prestas atención al resultado, hay un campo _score
. La cantidad de términos de la consulta que coinciden exactamente con el del índice invertido es una de las cosas que afecta la puntuación, pero guardemos el cálculo de la puntuación para otro día.
Cuándo usar uno u otro
Utilice el tipo de datos de campo keyword
si:
- Quieres una consulta de coincidencia exacta.
- Quieres que Elasticsearch funcione como otras bases de datos.
- Quieres usarlo para consultas comodín.
Utilice el tipo de datos de campo de texto si:
- Quieres crear un autocompletar.
- Quieres crear un sistema de búsqueda.
La comprensión de cómo text
y el campo keyword
de tipos de datos de trabajo es una de las cosas que tendrá que aprender en Elasticsearch, la diferencia parece simple pero importa mucho.
Querrá comprender y elegir el tipo de datos de campo adecuado para su caso de uso, si desea ambos tipos de datos de campo, puede usar la función de campos múltiples al crear el mapeo.
Por último, espero que este artículo le ayude a aprender Elasticsearch y a comprender las diferencias entre el texto y el tipo de datos de campo de palabras clave en Elasticsearch.
Espero qe te haya sido de utilidad. Gracias por leer este post.
Añadir comentario