Featured image of post Using Decay Functions in ElasticSearch to Perfect Your Search Results

Using Decay Functions in ElasticSearch to Perfect Your Search Results

Decay functions make your sorting more refined

A recent project required enhancements to existing search functionality:

  • Elasticsearch 7.6 (Note: parameters may vary across major versions)

Original search: Simple full-text indexing of title + body content
New requirements: Improve result sorting based on multiple factors - publication date (older content should score lower), manually assigned weight values (higher is better), and popularity metrics.

After researching the documentation, we found Elasticsearch natively supports this through Decay Functions.

Elasticsearch’s built-in decay functions work with numeric, date, and geo fields. You can define an ideal value (origin), and scores will decrease as values deviate from this ideal.

Supported parameters:

  • origin: The ideal value that receives full score (1.0)
  • offset: Values within ±offset range from origin also get full score
  • scale: Determines decay rate outside the offset range
  • decay: Acceptable score at edge of scaling range (default 0.5)

  • linear: Linear decay (scores drop to 0 beyond range)
  • exp: Rapid initial decay slowing over time
  • gauss: Bell-curve style decay (slow-fast-slow)

Our configuration example:

{
    "query": {
        // Using function scoring
        "function_score": {
            // Core search query
            "query": {
                "multi_match": {
                    "query": "blog",
                    "fields": [
                        "title^10",  // Title has 10x weight of body
                        "body"
                    ]
                }
            },
            // Multiply function score with original score
            "boost_mode": "multiply",
            // Sum scores from multiple functions
            "score_mode": "sum",
            "functions": [
                // Gaussian decay for date field (2020-04-27 as ideal)
                // Full score within 30 days, gauss decay from 30-90 days
                // Minimum score (0.5) beyond 90 days
                {
                    "gauss": {
                        "created_date": {
                            "origin": "2020-04-27",
                            "offset": "30d",
                            "scale": "60d",
                            "decay": 0.5
                        }
                    },
                    "weight": 1
                },
                // Linear decay for popularity score
                // Full score for 90-110 values, linear decay to 0.5 at 160
                {
                    "linear": {
                        "hot_value": {
                            "origin": 100,
                            "offset": 10,
                            "scale": 50,
                            "decay": 0.5
                        }
                    },
                    "weight": 2  // Double influence of this function
                }
            ]
        }
    }
}

References:
Elasticsearch Function Score Query Documentation
Zhihu Live: Full-Text Search with Elasticsearch