Recientemente comencé a usar ElasticSearch y parece que no puedo hacer que busque una parte de una palabra.
Ejemplo: tengo tres documentos de mi couchdb indexados en ElasticSearch:
{
"_id" : "1",
"name" : "John Doeman",
"function" : "Janitor"
}
{
"_id" : "2",
"name" : "Jane Doewoman",
"function" : "Teacher"
}
{
"_id" : "3",
"name" : "Jimmy Jackal",
"function" : "Student"
}
Así que ahora, quiero buscar todos los documentos que contengan "Doe"
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
Eso no devuelve ningún golpe. Pero si busco
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
Sí devuelve un documento (John Doeman).
Intenté configurar diferentes analizadores y diferentes filtros como propiedades de mi índice. También he intentado usar una consulta completa (por ejemplo:
{
"query": {
"term": {
"name": "Doe"
}
}
}
) Pero nada parece funcionar.
¿Cómo puedo hacer que ElasticSearch encuentre a John Doeman y Jane Doewoman cuando busco "Doe"?
ACTUALIZAR
Traté de usar el tokenizer y filtro nGram, como propuso Igor, así:
{
"index": {
"index": "my_idx",
"type": "my_type",
"bulk_size": "100",
"bulk_timeout": "10ms",
"analysis": {
"analyzer": {
"my_analyzer": {
"type": "custom",
"tokenizer": "my_ngram_tokenizer",
"filter": [
"my_ngram_filter"
]
}
},
"filter": {
"my_ngram_filter": {
"type": "nGram",
"min_gram": 1,
"max_gram": 1
}
},
"tokenizer": {
"my_ngram_tokenizer": {
"type": "nGram",
"min_gram": 1,
"max_gram": 1
}
}
}
}
}
El problema que tengo ahora es que todas y cada una de las consultas devuelven TODOS los documentos. Cualquier puntero? La documentación de ElasticSearch sobre el uso de nGram no es excelente ...
fuente
Respuestas:
También estoy usando nGram. Uso tokenizer estándar y nGram solo como filtro. He aquí mi arreglo:
Vamos a encontrar partes de palabras de hasta 50 letras. Ajuste el max_gram como lo necesite. En palabras alemanas puede ser realmente grande, así que lo configuré en un valor alto.
fuente
La búsqueda con comodines iniciales y finales será extremadamente lenta en un índice grande. Si desea poder buscar por prefijo de palabra, elimine el comodín inicial. Si realmente necesita encontrar una subcadena en medio de una palabra, sería mejor usar el tokenizer ngram.
fuente
Creo que no hay necesidad de cambiar ningún mapeo. Intenta usar query_string , es perfecto. Todos los escenarios funcionarán con el analizador estándar predeterminado:
Tenemos datos:
Escenario 1:
Respuesta:
Escenario 2:
Respuesta:
Escenario 3:
Respuesta:
EDITAR - Misma implementación con búsqueda elástica de datos de resorte https://stackoverflow.com/a/43579948/2357869
Una explicación más de cómo query_string es mejor que otros https://stackoverflow.com/a/43321606/2357869
fuente
sin cambiar sus asignaciones de índice, puede hacer una simple consulta de prefijo que realizará búsquedas parciales como espera
es decir.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
fuente
Pruebe la solución que se describe aquí: Búsquedas de subcadenas exactas en ElasticSearch
Para resolver el problema del uso del disco y el problema del término de búsqueda demasiado largo, se utilizan ngrams cortos de 8 caracteres de longitud (configurados con: "max_gram": 8 ). Para buscar términos con más de 8 caracteres, convierta su búsqueda en una consulta AND booleana que busque cada subcadena distinta de 8 caracteres en esa cadena. Por ejemplo, si un usuario buscó un patio grande (una cadena de 10 caracteres), la búsqueda sería:
"arge ya Y arge yar Y rge yard .
fuente
min_gram
ymax_gram
parece que dependería linealmente del tamaño de los valores de campo y el rango demin
ymax
? ¿Qué tan mal visto está usando algo como esto?ngram
haya un filtro sobre un tokenizador? ¿no podría simplemente tenerlo como un tokenizador y luego aplicar un filtro en minúsculas?index_ngram: { type: "custom", tokenizer: "ngram_tokenizer", filter: [ "lowercase" ] }
Lo probé y parece dar los mismos resultados usando la API de prueba del analizadorSi desea implementar la funcionalidad de autocompletar, entonces Completion Suggester es la solución más clara. La siguiente publicación de blog contiene una descripción muy clara de cómo funciona esto.
En dos palabras, es una estructura de datos en memoria llamada FST que contiene sugerencias válidas y está optimizada para una recuperación rápida y uso de memoria. Esencialmente, es solo un gráfico. Por ejemplo, y FST que contiene las palabras
hotel
,marriot
,mercure
,munchen
ymunich
se vería así:fuente
puedes usar regexp.
si usa esta consulta:
le dará todos los datos que comienzan con "J". Considere que desea recibir solo los dos primeros registros que terminan con "man" para que pueda usar esta consulta:
y si desea recibir todos los registros que en su nombre existen "m", puede usar esta consulta:
Esto funciona para mí. Y espero que mi respuesta sea adecuada para resolver su problema.
fuente
El uso de wilcards (*) previene el cálculo de una puntuación
fuente
Estoy usando esto y conseguí trabajar
fuente
No importa.
Tuve que mirar la documentación de Lucene. ¡Parece que puedo usar comodines! :-)
¡Hace el truco!
fuente