J'ai récemment commencé à utiliser ElasticSearch et je n'arrive pas à le faire rechercher une partie d'un mot.
Exemple: j'ai trois documents de mon couchdb indexés dans ElasticSearch:
{
"_id" : "1",
"name" : "John Doeman",
"function" : "Janitor"
}
{
"_id" : "2",
"name" : "Jane Doewoman",
"function" : "Teacher"
}
{
"_id" : "3",
"name" : "Jimmy Jackal",
"function" : "Student"
}
Alors maintenant, je veux rechercher tous les documents contenant "Doe"
curl http://localhost:9200/my_idx/my_type/_search?q=Doe
Cela ne renvoie aucun résultat. Mais si je cherche
curl http://localhost:9200/my_idx/my_type/_search?q=Doeman
Il renvoie un document (John Doeman).
J'ai essayé de définir différents analyseurs et différents filtres comme propriétés de mon index. J'ai également essayé d'utiliser une requête complète (par exemple:
{
"query": {
"term": {
"name": "Doe"
}
}
}
) Mais rien ne semble fonctionner.
Comment puis-je faire en sorte qu'ElasticSearch trouve à la fois John Doeman et Jane Doewoman lorsque je recherche "Doe"?
METTRE À JOUR
J'ai essayé d'utiliser le tokenizer et le filtre nGram, comme Igor l'a proposé, comme ceci:
{
"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
}
}
}
}
}
Le problème que j'ai maintenant est que chaque requête renvoie TOUS les documents. Des pointeurs? La documentation ElasticSearch sur l'utilisation de nGram n'est pas géniale ...
Réponses:
J'utilise aussi nGram. J'utilise un tokenizer standard et nGram juste comme filtre. Voici ma configuration:
Laissez-vous trouver des parties de mot jusqu'à 50 lettres. Ajustez le max_gram selon vos besoins. En allemand, les mots peuvent devenir vraiment gros, alors je l'ai défini sur une valeur élevée.
la source
La recherche avec des caractères génériques de début et de fin sera extrêmement lente sur un index volumineux. Si vous souhaitez pouvoir effectuer une recherche par préfixe de mot, supprimez le caractère générique de début. Si vous avez vraiment besoin de trouver une sous-chaîne au milieu d'un mot, vous feriez mieux d'utiliser le tokenizer ngram.
la source
Je pense qu'il n'est pas nécessaire de changer de mappage. Essayez d'utiliser query_string , c'est parfait. Tous les scénarios fonctionneront avec l'analyseur standard par défaut:
Nous avons des données:
Scénario 1:
Réponse:
Scénario 2:
Réponse:
Scénario 3:
Réponse:
EDIT - Même implémentation avec la recherche élastique de données de ressort https://stackoverflow.com/a/43579948/2357869
Une autre explication comment query_string est meilleur que les autres https://stackoverflow.com/a/43321606/2357869
la source
sans changer vos mappages d'index, vous pouvez faire une simple requête de préfixe qui fera des recherches partielles comme vous l'espérez
c'est à dire.
https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-prefix-query.html
la source
Essayez la solution avec est décrite ici: Recherches de sous-chaînes exactes dans ElasticSearch
Pour résoudre le problème d'utilisation du disque et le problème du terme de recherche trop long, des ngrammes courts de 8 caractères sont utilisés (configurés avec: "max_gram": 8 ). Pour rechercher des termes de plus de 8 caractères, transformez votre recherche en une requête booléenne AND recherchant chaque sous-chaîne distincte de 8 caractères dans cette chaîne. Par exemple, si un utilisateur recherchait une grande cour (une chaîne de 10 caractères), la recherche serait:
"arge ya ET arge yar ET rge yard .
la source
min_gram
etmax_gram
il semble qu'elle dépendrait linéairement de la taille des valeurs de champ et de la plage demin
etmax
. À quel point l'utilisation de quelque chose comme ça est mal vue?ngram
existe un filtre sur un tokenizer? ne pourriez-vous pas simplement l'avoir comme jeton et ensuite appliquer un filtre en minuscules ...index_ngram: { type: "custom", tokenizer: "ngram_tokenizer", filter: [ "lowercase" ] }
Je l'ai essayé et il semble donner les mêmes résultats en utilisant l'api de test de l'analyseurSi vous souhaitez implémenter la fonctionnalité de saisie semi-automatique, alors Completion Suggester est la solution la plus soignée. Le prochain article de blog contient une description très claire de son fonctionnement.
En deux mots, il s'agit d'une structure de données en mémoire appelée FST qui contient des suggestions valides et est optimisée pour une récupération rapide et une utilisation de la mémoire. Essentiellement, ce n'est qu'un graphique. Par exemple, et contenant SGO les mots
hotel
,marriot
,mercure
,munchen
etmunich
ressemblerait à ceci:la source
vous pouvez utiliser regexp.
si vous utilisez cette requête:
vous recevrez toutes les données dont le nom commence par "J". Considérez que vous souhaitez recevoir uniquement les deux premiers enregistrements dont le nom se termine par "man" afin que vous puissiez utiliser cette requête:
et si vous voulez recevoir tous les enregistrements qui dans leur nom existent "m", vous pouvez utiliser cette requête:
Cela fonctionne pour moi. Et j'espère que ma réponse sera appropriée pour résoudre votre problème.
la source
L'utilisation de wilcards (*) empêche le calcul d'un score
la source
J'utilise ça et j'ai travaillé
la source
Ça ne fait rien.
J'ai dû regarder la documentation Lucene. Il semble que je puisse utiliser des jokers! :-)
fait l'affaire!
la source