Is it possible to boost 'newest' items using elasticsearch? (FOQElasticaBundle) Is it possible to boost 'newest' items using elasticsearch? (FOQElasticaBundle) symfony symfony

Is it possible to boost 'newest' items using elasticsearch? (FOQElasticaBundle)


Whew, after much experimentation and hours of trawling the Interweb I finally managed to get the desired behavior! (Full credit goes to Clinton Gormley.)

Mapping configuration:

mappings:    title: { boost: 8 }    summary: { boost: 5 }    text: { boost: 3 }    author:    publishedAt: { type: date }

Here is the code using the PHP client, Elastica, to dynamically build the query to boost using the original mapping AND the published date:

$query = new \Elastica_Query_Bool();$query->addMust(new \Elastica_Query_QueryString($queryString));$ranges = array();for ($i = 1; $i <= 5; $i++) {    $date = new \DateTime("-$i month");    $currentRange = new \Elastica_Query_Range();    $currentRange->addField('publishedAt', array(        'boost' => (6 - $i),        'gte' => $date->getTimestamp()    ));    $ranges[] = $currentRange->toArray();}$query->addShould($ranges);/** @var $pagerfanta Pagerfanta */$pagerfanta = $this->getFinder()->findPaginated($query);

And for those of you more interested in the raw elasticsearch query (only with 3 date ranges for brevity)...

curl -XPOST 'http://localhost:9200/website/story/_search?pretty=true' -d '{  "query" : {    "bool" : {      "must" : {        query_string: {          query: "<search term(s)>"        }      },      "should" : [        {          "range" : {            "publishedAt" : {              "boost" : 5,              "gte" : "<1 month ago>"            }          }        },        {          "range" : {            "publishedAt" : {              "boost" : 4,              "gte" : "<2 months ago>"            }          }        },        {          "range" : {            "publishedAt" : {              "boost" : 3,              "gte" : "<3 months ago>"            }          }        }      ]    }  }}'


You can use a decay scoring function, to decrease the scoring versus time :

{ "query": { "function_score": {    "functions": [     {      "linear": {        "pubdate": {          "origin": 1398673886,          "scale": "1h",          "offset": 0,          "decay": 0.1        }      }    }    ]   }  } }


A full elasticsearch 5 example based on function_score. See this blogpost and function_score docs for more info.

Allows for boosting more recent entries based on multiple date ranges, with varying strengths, on a gaussian curve without "hard cutoffs".

{    "query": {        "function_score": {            "score_mode": "sum", // All functions outputs get summed            "boost_mode": "multiply", // The documents relevance is multiplied with the sum            "functions": [                {                    // The relevancy of old posts is multiplied by at least one.                    // Remove if you want to exclude old posts                    "weight": 1                },                {                    // Published this month get a big boost                    "weight": 5,                    "gauss": {                        "date": { // <- Change to your date field name                            "origin": "2017-04-07", // Change to current date                            "scale": "31d",                            "decay": 0.5                        }                    }                },                {                    // Published this year get a boost                    "weight": 2,                    "gauss": {                        "date": { // <- Change to your date field name                            "origin": "2017-04-07", // Change to current date                            "scale": "356d",                            "decay": 0.5                        }                    }                }            ],            "query": {                // The rest of your search here, change to something relevant                "match": { "title": "< your search string >" }            }        }    }}