Auto-complétion


(Jeje Pinot) #1

Bonjour,

Je cherche à faire de l’auto-complétion sur des champs de type "attachment".
J'ai suivis quelques tutos sur le web et j'en suis arrivé à un résultat de ce type:

Requête:

curl -X POST $ES_HOST/$ES_INDEX/$ES_INDEX_TYPE/_search?pretty -d '
{
	"size": 0,
	"query" : {
		"prefix": {
			"autocomplete": {
				"value": "auth"
			}
		}
	},
	"aggs": {
		"autocomplete": {
			"terms": {
				"field": "autocomplete",
				"order": {
					"_count": "desc"
				},
				"include": {
					"pattern": "auth.*"
				}
			}
		}
	}
}'

Résultat:

{
  "took" : 20,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 16,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "aggregations" : {
    "autocomplete" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 138,
      "buckets" : [ {
        "key" : "auth",
        "doc_count" : 16
      }, {
        "key" : "authe",
        "doc_count" : 16
      }, {
        "key" : "authen",
        "doc_count" : 16
      }, {
        "key" : "authent",
        "doc_count" : 16
      }, {
        "key" : "authenti",
        "doc_count" : 16
      }, {
        "key" : "authentif",
        "doc_count" : 16
      }, {
        "key" : "authentifi",
        "doc_count" : 16
      }, {
        "key" : "authentific",
        "doc_count" : 15
      }, {
        "key" : "authentifica",
        "doc_count" : 15
      }, {
        "key" : "authentificat",
        "doc_count" : 15
      } ]
    }
  }
}

Comme vous pouvez le voir, l'auto-complétion fonctionne plutôt bien, mais elle renvoie des résultats qui ne sont pas dans mes documents (comme authe, authen, authent, authenti, authentif, ...). Si je ne me trompe pas, je récupère tous les Edge NGram qui match avec auth.

Voici mon index:

curl -X PUT $ES_HOST/$ES_INDEX/?pretty -d '
{
	"settings": {
		"index": {
			"analysis": {
			
				"filter": {
					"edgeNGram_filter": {
						"type": "edgeNGram",
						"side": "front",
						"min_gram": "1",
						"max_gram": "20"
					}
				},
				
				"analyzer": { 					
					"autocomplete_index_analyzer": {
						"type": "custom",
						"char_filter": ["html_strip"],
						"tokenizer": "standard",
						"filter": ["standard", "lowercase", "asciifolding", "edgeNGram_filter"]
					},
					"autocomplete_search_analyzer": {
						"type": "custom",
						"char_filter": ["html_strip"],
						"tokenizer": "standard",
						"filter": ["standard", "lowercase", "asciifolding"]
					}						
				}
			}
		}
	}
}'

mon Mapping:

curl -X PUT $ES_HOST/$ES_INDEX/$ES_INDEX_TYPE/_mapping?pretty -d '
{
	"properties": {
	
		"autocomplete": {
			"type": "string",
			"search_analyzer": "autocomplete_search_analyzer",
			"index_analyzer": "autocomplete_index_analyzer"
		},   		
		"file": {
			"type": "attachment",
			"path": "full",
			"fields": {
				"name": {"store": "yes"},
				"language": {"store": "yes"},
				"file": {
					"store": "yes",
					"term_vector": "with_positions_offsets",
					"copy_to": ["autocomplete"]
				}
			}
		}
		
	}
}'

et enfin la façon dont j'index mes documents:

curl -X POST $ES_HOST/$ES_INDEX/$ES_INDEX_TYPE?pretty -d '
{
	"path": "chemin/du/document",
	"file" : {
		"_name": "mon_nom",
		"_language": "fr",
		"_indexed_chars": "-1", 
		"_content": "... base 64 ..."
	}
}'

Ma demande est la suivante, que faire pour obtenir uniquement les mots existants dans les champs "file" et "path" (Authentification, Authentifié, Authentifier, ...) ?
Je suis également preneur de tout conseil qui m'aiderait à mieux comprendre et gérer ElasticSearch :stuck_out_tongue:

En vous remerciant !

Jérôme Pinot


(Camilo Sierra) #2

salut! tu peut changer la function prefix pour la multi_match, dans le champ fields tu peut ecrire : file._name, path !
et dans le type utilise type phrase_prefix pour avoir le même comportement d'autocompletion.

il faut pas oublier de definir max_expansions pour avoir des meilleurs perfo dans la query! et tu peut faire essayer aussi de tester en supprimant le edgeNGram_filter dans l'indexation, si je me trompe pas le phrase_prefix continue a marcher et a donner des bonnes resultats sans edge NGram et tu vas reduire la taille de ton index!

https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-multi-match-query.html


(Jeje Pinot) #3

Bonjour,

Merci de ta réponse, j'ai essayé d'utiliser la combinaison multi_match et phrase_prefix et en effet, j'obtiens le type de résultat que je souhaite, cependant il ne cherche plus dans le champs file.content de mon document. La requête ne match qu'avec les champs path et file.name de mes documents.
Le champs file.content (base64) est ignoré.

curl -X POST $ES_HOST/$ES_INDEX/$ES_INDEX_TYPE/_search?pretty -d '
{
	"fields": ["name", "path"],
	"query": {
		"multi_match": {
			"query": "auth",
			"type": "phrase_prefix",
			"fields": ["file._name", "path", "file._content"],
			"max_expansions" : 10
		}
	},
	"aggs": {
		"autocomplete": {
			"terms": {
				"field": "file",
				"order": {
					"_count": "desc"
				},
				"include": {
					"pattern": "auth.*"
				}
			}
		}
	}
}'

Une idée de la raison du pourquoi du comment ? :blush: Merci encore !


(Camilo Sierra) #4

hello @Jeje_Pinot je viens de tester dans mon projet j'indexe aussi des fichiers avec le plugin @attachements et je arrive a chercher dans le content, essaie d'utiliser la function match juste avec content pour voir si ça marche!


(system) #5