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 >" } } } }}