Boosting Recent Activity in Elasticsearch Search Results
Understand different techniques, including function_score, decay functions, and bucketing

Elasticsearch has long been a powerful tool for indexing and searching massive data sets. In this article, we’ll dive into a specific use case, enhancing a search ranking system in Elasticsearch to prioritize profiles that have been recently active. From exploring various techniques to selecting our final solution, we’ll detail how we leveraged Elasticsearch to boost engagement on our platform.
Introduction to the Challenge
We faced a unique problem within our Elasticsearch-based search system: how to rank profiles based on recent activity without overshadowing our existing complex ranking and matching system. The goal was to segment activity into three categories:
0–10 days: High weight
10–60 days: Medium weight
Beyond 60 days: Standard weight
And all of this needed to happen within our existing Elasticsearch setup.
Option 1: Applying a Multiplier with Elasticsearch’s function_score
Understanding the Method
The first approach involved using the Elasticsearch’s function_score
query. We retrieved the value of "last_active_at" from each document and applied a square root modifier on this value, then multiplied it by a factor to adjust the _score
for that document.
{
"query": {
"function_score": {
"query": { /* your current query */ },
"functions": [
{
"field_value_factor": {
"field": "last_active_at",
"modifier": "sqrt",
"factor": 1.2
}
}
],
"boost_mode": "multiply"
}
},
"size": 20
}
Pros
Control: Allows precise control over scores.
Cons
Arbitrary Numbers: The final values can be non-intuitive and require tuning.
Rigidity: Does not offer a smooth transition between time ranges.
Option 2: Using a Decay Function in Elasticsearch
Understanding the Method
Elasticsearch’s built-in decay functions, such as gauss, provide a way to gently decay scores over time.
{
"query": {
"function_score": {
"query": { /* your current query */ },
"functions": [
{
"gauss": {
"last_active_at": {
"origin": "now",
"scale": "15d",
"offset": "3d",
"decay": 0.5
}
}
}
],
"boost_mode": "multiply"
}
},
"size": 20
}
Pros
Smooth Transition: Native to Elasticsearch and provides intuitive score decay.
Flexibility: Can be fine-tuned to specific needs within Elasticsearch.
Cons
Complexity: Requires specific adjustments to align with the desired strategy.
Option 3: The Bucketing Solution in Elasticsearch (Our Final Choice)
Understanding the Method
We crafted a precise solution within Elasticsearch, using multiple gauss functions.
{
"query": {
"function_score": {
"query": { /* your current query */ },
"functions": [
{
"gauss": {
"last_active_at": {
"origin": "now",
"scale": "3d",
"decay": 1.0
}
}
},
{
"gauss": {
"last_active_at": {
"origin": "now-3d",
"scale": "27d",
"decay": 0.8
}
}
}
],
"score_mode": "max",
"boost_mode": "multiply"
}
},
"size": 20
}
Pros
Precision: Achieves exact bucketing within Elasticsearch.
Flexibility: Combines smooth decay with score control, all in Elasticsearch.
Cons
Complexity: More intricate to set up and required fine-tuning within Elasticsearch.
Performance Implications of Different Methods
When considering different strategies for boosting recently active profiles in our search results, it’s crucial to also understand how each method may impact query performance. Here’s a look at the three methods described earlier:
Option 1: Applying a Multiplier with Elasticsearch’s function_score
Performance Impact
Moderate Complexity: This method is relatively straightforward but might introduce some computational overhead due to the square root calculation and multiplication.
Index Structure: If “last_active_at” is indexed properly, the performance impact is generally minor.
Option 2: Using Decay Functions (gauss, exp, or linear)
Performance Impact
More Computationally Intensive: Calculating decay functions can be more computationally taxing, especially when using the Gaussian function.
Smooth Decay: The computational complexity can be worth the payoff if you require a more nuanced decrease in scores over time.
Option 3: Final Bucketing Solution with Multiple gauss
Functions
Performance Impact
Complexity: Multiple
gauss
functions add complexity, and calculating the max score among different functions may slow down query execution slightly.Optimization Opportunity: Fine-tuning the scales and decay factors can help in achieving the desired performance balance. Ensuring proper indexing and using optimal data types can mitigate the performance cost.
Conclusion
Our journey led us to a robust solution within the Elasticsearch environment that met our specific requirements for boosting profiles based on recent activity. By utilizing the powerful features of Elasticsearch, we tailored our search results to create a more engaging platform for our users.
Elasticsearch proved to be a versatile and capable tool, accommodating our complex needs and allowing for precise tuning. As with any robust system, the path to perfection involved experimentation and careful consideration of various approaches.
Whether you’re new to Elasticsearch or an experienced veteran, we hope this exploration aids you in your next adventure in search optimization. Happy coding! 🚀
🔗 Connect with me on LinkedIn!
I hope you found this article helpful! If you’re interested in learning more and staying up-to-date with my latest insights and articles, don’t hesitate to connect with me on LinkedIn.
Let’s grow our networks, engage in meaningful discussions, and share our experiences in the world of software development and beyond. Looking forward to connecting with you! 😊