web-dev-qa-db-fra.com

ElasticSearch - augmenter la pertinence en fonction de la valeur du champ

Besoin de trouver un moyen dans ElasticSearch pour augmenter la pertinence d'un document en fonction d'une valeur particulière d'un champ. Plus précisément, il y a un champ spécial dans tous mes documents où plus la valeur du champ est élevée, plus le document qui le contient doit être pertinent, quelle que soit la recherche.

Tenez compte de la structure de document suivante:

{
    "_all" : {"enabled" : "true"},
    "properties" : {
        "_id":            {"type" : "string",  "store" : "yes", "index" : "not_analyzed"},
        "first_name":     {"type" : "string",  "store" : "yes", "index" : "yes"},
        "last_name":      {"type" : "string",  "store" : "yes", "index" : "yes"},
        "boosting_field": {"type" : "integer", "store" : "yes", "index" : "yes"}
        }
}

J'aimerais que les documents avec une valeur boosting_field plus élevée soient intrinsèquement plus pertinents que ceux avec une valeur boosting_field inférieure. Ce n'est qu'un point de départ - la correspondance entre la requête et les autres champs sera également prise en compte pour déterminer le score de pertinence final de chaque document dans la recherche. Mais, toutes choses étant égales par ailleurs, plus le champ de boosting est élevé, plus le document est pertinent.

Quelqu'un a une idée sur la façon de procéder?

Merci beaucoup!

62
Clay Wardell

Vous pouvez soit booster au moment de l'index ou au moment de la requête. Je préfère généralement augmenter le temps de requête, même si cela rend les requêtes un peu plus lentes, sinon je devrais réindexer chaque fois que je veux changer mes facteurs de boost, qui nécessitent généralement un réglage fin et doivent être assez flexibles.

Il existe différentes façons d'appliquer le boost de temps de requête à l'aide de la requête DSL elasticsearch:

Les trois premières requêtes sont utiles si vous souhaitez donner un coup de pouce spécifique aux documents qui correspondent à des requêtes ou des filtres spécifiques. Par exemple, si vous souhaitez booster uniquement les documents publiés au cours du dernier mois. Vous pouvez utiliser cette approche avec votre boosting_field mais vous devez définir manuellement certains intervalles boosting_field et leur donner un boost différent, ce qui n'est pas terrible.

La meilleure solution serait d'utiliser un Requête de score personnalisé , qui vous permet de faire une requête et de personnaliser son score à l'aide d'un script. C'est assez puissant, avec le script, vous pouvez directement modifier le score lui-même. Tout d'abord, je mettrais les valeurs boosting_field à une valeur de 0 à 1 par exemple, afin que votre score final ne devienne pas un grand nombre. Pour ce faire, vous devez prédire quelles sont plus ou moins les valeurs minimales et maximales que le champ peut contenir. Disons au minimum 0 et au maximum 100000 par exemple. Si vous modifiez la valeur boosting_field à un nombre compris entre 0 et 1, vous pouvez ajouter le résultat au score réel comme ceci:

{
    "query" : {
        "custom_score" : {
            "query" : {
                "match_all" : {}
            },
            "script" : "_score + (1 * doc.boosting_field.doubleValue / 100000)"
        }
    }
}

Vous pouvez également envisager d'utiliser le boosting_field comme facteur de boost (_score * plutôt que _score +), mais vous devrez ensuite le mettre à l'échelle à un intervalle avec une valeur minimale de 1 (ajoutez simplement +1).

Vous pouvez même régler le résultat afin de changer son importance en ajoutant un poids à la valeur que vous utilisez pour influencer le score. Vous en aurez encore plus besoin si vous devez combiner plusieurs facteurs de stimulation afin de leur donner un poids différent.

69
javanna

Avec une version récente d'Elasticsearch (version 1.3+), vous voudrez utiliser des "requêtes de score de fonction":

http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

Une recherche de chaîne de requête notée ressemble à ceci:

{
 'query': {
        'function_score': {
            'query': { 'query_string': { 'query': 'my search terms' } },
            'functions': [{ 'field_value_factor': { 'field': 'my_boost' } }]
        }
    }
}

"my_boost" est un champ numérique dans votre index de recherche qui contient le facteur de boost pour les documents individuels. Peut ressembler à ceci:

{ "my_boost": { "type": "float", "index": "not_analyzed" } }
13
Simon Steinberger

si vous voulez éviter de faire le boost à chaque fois dans la requête, vous pouvez envisager de l'ajouter directement à votre mapping en ajoutant "boost: factor.

Votre mappage peut donc ressembler à ceci:

{
    "_all" : {"enabled" : "true"},
    "properties" : {
        "_id":            {"type" : "string",  "store" : "yes", "index" : "not_analyzed"},
        "first_name":     {"type" : "string",  "store" : "yes", "index" : "yes"},
        "last_name":      {"type" : "string",  "store" : "yes", "index" : "yes"},
        "boosting_field": {"type" : "integer", "store" : "yes", "index" : "yes", "boost" : 10.0,}
        }
}
3
HolgT