search - elastic - lucene query and or
ElasticSearch-Búsqueda de nombres humanos (1)
Primero, recreé tu configuración actual en Play: https://www.found.no/play/gist/867785a709b4869c5543
Si vas allí, cambia a la pestaña "Análisis" para ver cómo se transforma el texto:
Tenga en cuenta, por ejemplo, que Heaney
termina como tokenizado como [hn, heanei]
con el search_analyzer
y como [HN, heanei]
con el index_analyzer
. Tenga en cuenta la diferencia de caso para el término de metafonía. Por lo tanto, ese no está haciendo juego.
La consulta fuzzy
no hace análisis de texto de tiempo de consulta. Por lo tanto, terminas comparando Heavey
con heanei
. Esto tiene una distancia Damerau-Levenshtein más larga de lo que permiten tus parámetros.
Lo que realmente quieres hacer es usar la funcionalidad difusa de la match
. Match hace análisis de texto de tiempo de consulta, y tiene un parámetro de confusión.
En cuanto a la fuzziness
, esto cambió un poco en Lucene 4. Antes, normalmente se especificaba como un flotador. Ahora debe especificarse como la distancia permitida. Hay una solicitud de extracción pendiente para aclarar eso: https://github.com/elasticsearch/elasticsearch/pull/4332/files
La razón por la que estás recibiendo personas sin el nombre Michael
es que estás haciendo un bool.should
. Esto tiene semántica OR. Es suficiente que una coincida, pero en cuanto a puntuación, es mejor cuanto más coincida.
Por último, combinar todo ese filtrado en el mismo término no es necesariamente el mejor enfoque. Por ejemplo, no puedes saber y mejorar la ortografía exacta. Lo que debes considerar es usar un multi_field para procesar el campo de muchas maneras.
Aquí hay un ejemplo con el que puedes jugar , con los comandos Curl para recrearlo a continuación. Sin embargo, omitiría usar la lectora "porter" por completo. Lo guardé solo para mostrar cómo funciona multi_field. Usar una combinación de coincidencia, coincidencia con borrosidad y correspondencia fonética debería llevarlo lejos. (Asegúrate de no permitir la falta de claridad cuando haces una coincidencia fonética, o obtendrás una coincidencia difusa inútil) :-)
#!/bin/bash
export ELASTICSEARCH_ENDPOINT="http://localhost:9200"
# Create indexes
curl -XPUT "$ELASTICSEARCH_ENDPOINT/play" -d ''{
"settings": {
"analysis": {
"text": [
"Michael",
"Heaney",
"Heavey"
],
"analyzer": {
"metaphone": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"my_metaphone"
]
},
"porter": {
"type": "custom",
"tokenizer": "standard",
"filter": [
"lowercase",
"porter_stem"
]
}
},
"filter": {
"my_metaphone": {
"encoder": "metaphone",
"replace": false,
"type": "phonetic"
}
}
}
},
"mappings": {
"jr": {
"properties": {
"pty_surename": {
"type": "multi_field",
"fields": {
"pty_surename": {
"type": "string",
"analyzer": "simple"
},
"metaphone": {
"type": "string",
"analyzer": "metaphone"
},
"porter": {
"type": "string",
"analyzer": "porter"
}
}
}
}
}
}
}''
# Index documents
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_bulk?refresh=true" -d ''
{"index":{"_index":"play","_type":"jr"}}
{"pty_surname":"Heaney"}
{"index":{"_index":"play","_type":"jr"}}
{"pty_surname":"Heavey"}
''
# Do searches
curl -XPOST "$ELASTICSEARCH_ENDPOINT/_search?pretty" -d ''
{
"query": {
"bool": {
"should": [
{
"bool": {
"should": [
{
"match": {
"pty_surname": {
"query": "heavey"
}
}
},
{
"match": {
"pty_surname": {
"query": "heavey",
"fuzziness": 1
}
}
},
{
"match": {
"pty_surename.metaphone": {
"query": "heavey"
}
}
},
{
"match": {
"pty_surename.porter": {
"query": "heavey"
}
}
}
]
}
}
]
}
}
}
''
Tengo una gran base de datos de nombres, principalmente de Escocia. Actualmente estamos produciendo un prototipo para reemplazar una pieza existente de software que realiza la búsqueda. Esto todavía está en producción y nuestro objetivo es obtener nuestros resultados lo más cerca posible de los resultados actuales de la misma búsqueda.
Esperaba que alguien me pudiera ayudar, estoy ingresando en una búsqueda en Elastic Search, la consulta es "Michael Heaney", obtengo algunos resultados extravagantes. La búsqueda actual devuelve dos apellidos principales, estos son - "Heaney" y "Heavey" todos con el nombre de "Michael", puedo obtener los resultados de "Heaney" en Elastic Search sin embargo no puedo obtener "Heavey" y ES también devuelve personas sin el apellido "Michael"; sin embargo, agradezco que eso se deba a que forma parte de la consulta difusa. Sé que este es un caso de uso limitado, ya que es solo una búsqueda, pero obtener este resultado y saber cómo puedo obtenerlo ayudará.
Gracias.
Cartografía
{
"jr": {
"_all": {
"enabled": true,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer"
},
"properties": {
"pty_forename": {
"type": "string",
"index": "analyzed",
"boost": 2,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer",
"store": "yes"
},
"pty_full_name": {
"type": "string",
"index": "analyzed",
"boost": 4,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer",
"store": "yes"
},
"pty_surname": {
"type": "string",
"index": "analyzed",
"boost": 4,
"index_analyzer": "index_analyzer",
"search_analyzer": "search_analyzer",
"store": "yes"
}
}
}
}''
Configuración de índice
{
"settings": {
"number_of_shards": 2,
"number_of_replicas": 0,
"analysis": {
"analyzer": {
"index_analyzer": {
"tokenizer": "standard",
"filter": [
"standard",
"my_delimiter",
"lowercase",
"stop",
"asciifolding",
"porter_stem",
"my_metaphone"
]
},
"search_analyzer": {
"tokenizer": "standard",
"filter": [
"standard",
"my_metaphone",
"synonym",
"lowercase",
"stop",
"asciifolding",
"porter_stem"
]
}
},
"filter": {
"synonym": {
"type": "synonym",
"synonyms_path": "synonyms/synonyms.txt"
},
"my_delimiter": {
"type": "word_delimiter",
"generate_word_parts": true,
"catenate_words": false,
"catenate_numbers": false,
"catenate_all": false,
"split_on_case_change": false,
"preserve_original": false,
"split_on_numerics": false,
"stem_english_possessive": false
},
"my_metaphone": {
"type": "phonetic",
"encoder": "metaphone",
"replace": false
}
}
}
}
}''
Borroso
{
"from":0, "size":100,
"query": {
"bool": {
"should": [
{
"fuzzy": {
"pty_surname": {
"min_similarity": 0.2,
"value": "Heaney",
"prefix_length": 0,
"boost": 5
}
}
},
{
"fuzzy": {
"pty_forename": {
"min_similarity": 1,
"value": "Michael",
"prefix_length": 0,
"boost": 1
}
}
}
]
}
}
}