web-dev-qa-db-fra.com

Elasticsearch: rechercher une correspondance de sous-chaîne

Je veux effectuer une correspondance exacte de Word et une correspondance partielle de Word/sous-chaîne. Par exemple, si je recherche "rasoir pour hommes", je devrais pouvoir trouver "rasoir pour hommes" dans le résultat. Mais au cas où je rechercherais "rasoir en", je devrais aussi pouvoir trouver "rasoir pour homme" dans le résultat. J'utilise les paramètres et les mappages suivants:

Paramètres d'index:

PUT /my_index
{
    "settings": {
        "number_of_shards": 1, 
        "analysis": {
            "filter": {
                "autocomplete_filter": { 
                    "type":     "Edge_ngram",
                    "min_gram": 1,
                    "max_gram": 20
                }
            },
            "analyzer": {
                "autocomplete": {
                    "type":      "custom",
                    "tokenizer": "standard",
                    "filter": [
                        "lowercase",
                        "autocomplete_filter" 
                    ]
                }
            }
        }
    }
}

Mappages:

PUT /my_index/my_type/_mapping
{
    "my_type": {
        "properties": {
            "name": {
                "type":            "string",
                "index_analyzer":  "autocomplete", 
                "search_analyzer": "standard" 
            }
        }
    }
}

Insérer des enregistrements:

POST /my_index/my_type/_bulk
{ "index": { "_id": 1            }}
{ "name": "men's shaver" }
{ "index": { "_id": 2            }}
{ "name": "women's shaver" }

Requête:

1. Pour effectuer une recherche par correspondance exacte de phrases -> "hommes"

POST /my_index/my_type/_search
{
    "query": {
        "match": {
            "name": "men's"
        }
    }
}

La requête ci-dessus renvoie "rasoir pour homme" dans le résultat de retour.

2. Pour rechercher par correspondance partielle de mots -> "en"

POST /my_index/my_type/_search
{
    "query": {
        "match": {
            "name": "en's"
        }
    }
}

La requête ci-dessus ne renvoie rien.

J'ai également essayé la requête suivante

POST /my_index/my_type/_search
{
    "query": {
        "wildcard": {
           "name": {
              "value": "%en's%"
           }
        }
    }
}

Toujours rien. Je pensais que c'était à cause du filtre de type "Edge_ngram" sur Index qui ne pouvait pas trouver "correspondance partielle Word/sbustring". J'ai également essayé le filtre de type "n-gram" mais cela ralentit beaucoup la recherche.

Veuillez me suggérer comment obtenir à la fois une correspondance de phrase exacte et une correspondance de phrase partielle en utilisant le même paramètre d'index.

45
Kruti Shukla

Pour rechercher des correspondances de champs partielles et des correspondances exactes, cela fonctionnera mieux si vous définissez les champs comme "non analysés" ou comme mots clés (plutôt que du texte), puis utilisez une requête avec caractères génériques .

Voir aussi ceci .

Pour utiliser une requête avec caractère générique, ajoutez * aux deux extrémités de la chaîne que vous recherchez:

POST /my_index/my_type/_search
{
"query": {
    "wildcard": {
       "name": {
          "value": "*en's*"
       }
    }
}
}

Pour l'utiliser avec insensibilité à la casse , utilisez un analyseur personnalisé avec un filtre en minuscules et un tokenizer de mots clés .

Analyseur personnalisé:

"custom_analyzer": {
            "tokenizer": "keyword",
            "filter": ["lowercase"]
        }

Rendre la chaîne de recherche en minuscules

Si vous obtenez une chaîne de recherche sous la forme AsD : remplacez-la par * asd *

61
BlackPOP