Decay Ranker OverviewCompatible with Milvus 2.6.x
In traditional vector search, results are ranked purely by vector similarity—how closely vectors match in mathematical space. But in real-world applications, what makes content truly relevant often depends on more than just semantic similarity.
Consider these everyday scenarios:
A news search where yesterday’s article should rank higher than a similar article from three years ago
A restaurant finder that prioritizes venues 5 minutes away over those requiring a 30-minute drive
An e-commerce platform that boosts trending products even when they’re slightly less similar to the search query
These scenarios all share a common need: balancing vector similarity with other numeric factors like time, distance, or popularity.
Decay rankers in Milvus address this need by adjusting search rankings based on numeric field values. They allow you to balance vector similarity with “freshness,” “nearness,” or other numeric properties of your data, creating more intuitive and contextually relevant search experiences.
Limits
Decay ranking cannot be used with grouping searches.
The field used for decay ranking must be numeric (
INT8
,INT16
,INT32
,INT64
,FLOAT
, orDOUBLE
).Each decay ranker can only use one numeric field.
How it works
Decay ranking enhances traditional vector search by incorporating numeric factors like time or geo distance into the ranking process. The entire process follows these stages:
Stage 1: Calculate normalized similarity scores
First, Milvus calculates and normalizes vector similarity scores to ensure consistent comparison:
For L2 and JACCARD distance metrics (where lower values indicate higher similarity):
normalized_score = 1.0 - (2 × arctan(score))/π
This transforms distances into similarity scores between 0-1, where higher is better.
For IP, COSINE, and BM25 metrics (where higher scores already indicate better matches): Scores are used directly without normalization.
Stage 2: Calculate decay scores
Next, Milvus calculates a decay score based on the numeric field value (like timestamp or distance) using your selected decay ranker:
Each decay ranker transforms raw numeric values into normalized relevance scores between 0-1
The decay score represents how relevant an item is based on its “distance” from the ideal point
The specific calculation formula varies depending on the decay ranker type. For details on how to calculate a decay score, refer to the dedicated pages for Gaussian Decay, Exponential Decay, Linear Decay.
Stage 3: Compute final scores
Finally, Milvus combines the normalized similarity score and decay score to produce the final ranking score:
final_score = normalized_similarity_score × decay_score
In cases of hybrid search (combining multiple vector fields), Milvus takes the maximum normalized similarity score among search requests:
final_score = max([normalized_score₁, normalized_score₂, ..., normalized_scoreₙ]) × decay_score
For example, if a research paper scores 0.82 from vector similarity and 0.91 from BM25-based text retrieval in a hybrid search, Milvus uses 0.91 as the base similarity score before applying the decay factor.
Decay ranking in action
Let’s see decay ranking in a practical scenario—searching for “AI research papers” with time-based decay:
In this example, decay scores reflect how relevance diminishes with time—newer papers receive scores closer to 1.0, older papers receive lower scores. These values are calculated using a specific decay ranker. For details, refer to Choose the right decay ranker.
Paper |
Vector Similarity |
Normalized Similarity Score |
Publication Date |
Decay Score |
Final Score |
Final Rank |
---|---|---|---|---|---|---|
Paper A |
High |
0.85 ( |
2 weeks ago |
0.80 |
0.68 |
2 |
Paper B |
Very High |
0.92 ( |
6 months ago |
0.45 |
0.41 |
3 |
Paper C |
Medium |
0.75 ( |
1 day ago |
0.98 |
0.74 |
1 |
Paper D |
Medium-High |
0.76 ( |
3 weeks ago |
0.70 |
0.53 |
4 |
Without decay reranking, Paper B would rank highest based on pure vector similarity (0.92). However, with decay reranking applied:
Paper C jumps to position #1 despite medium similarity because it’s very recent (published yesterday)
Paper B drops to position #3 despite excellent similarity because it’s relatively old
Paper D uses L2 distance (where lower is better), so its score is normalized from 1.2 to 0.76 before applying decay
Choose the right decay ranker
Milvus offers distinct decay rankers - gauss
, exp
, linear
, each designed for specific use cases:
Decay Ranker |
Characteristics |
Ideal Use Cases |
Example Scenario |
---|---|---|---|
Gaussian ( |
Natural-feeling gradual decline that extends moderately |
|
In a restaurant search, quality venues 3 km away remain discoverable, though ranked lower than nearby options |
Exponential ( |
Rapidly decreases at first but maintains a long tail |
|
In a news app, yesterday's stories rank much higher than week-old content, but highly relevant older articles can still appear |
Linear ( |
Consistent, predictable decline with a clear cutoff |
|
In an event finder, events beyond a two-week future window simply don't appear at all |
For detailed information about how each decay ranker calculates scores and specific decline patterns, refer to the dedicated documentation:
Implementation example
Decay rankers can be applied to both standard vector search and hybrid search operations in Milvus. Below are the key code snippets for implementing this feature.
Before using decay functions, you must first create a collection with appropriate numeric fields (like timestamps, distances, etc.) that will be used for decay calculations. For complete working examples including collection setup, schema definition, and data insertion, refer to Tutorial: Implement Time-based Ranking in Milvus.
Create a decay ranker
To implement decay ranking, first define a Function
object with the appropriate configuration:
from pymilvus import Function, FunctionType
# Create a decay function for timestamp-based decay
decay_ranker = Function(
name="time_decay", # Function identifier
input_field_names=["timestamp"], # Numeric field to use for decay
function_type=FunctionType.RERANK, # Must be set to RERANK for decay rankers
params={
"reranker": "decay", # Specify decay reranker. Must be "decay"
"function": "gauss", # Choose decay function type: "gauss", "exp", or "linear"
"origin": int(datetime.datetime(2025, 1, 15).timestamp()), # Reference point
"scale": 7 * 24 * 60 * 60, # 7 days in seconds
"offset": 24 * 60 * 60, # 1 day no-decay zone
"decay": 0.5 # Half score at scale distance
}
)
Parameter |
Required? |
Description |
Value/Example |
---|---|---|---|
|
Yes |
Identifier for your function used when executing searches. Choose a descriptive name relevant to your use case. |
|
|
Yes |
Numeric field for decay score calculation. Determines which data attribute will be used for calculating decay (e.g., timestamps for time-based decay, coordinates for location-based decay). Must be a field in your collection that contains relevant numeric values. Supports INT8/16/32/64, FLOAT, DOUBLE. |
|
|
Yes |
Specifies the type of function being created.
Must be set to |
|
|
Yes |
Specifies the reranking method to use.
Must be set to |
|
|
Yes |
Specifies which mathematical decay ranker to apply. Determines the curve shape of relevance decline. See Choose the right decay ranker section for guidance on selecting the appropriate function. |
|
|
Yes |
Reference point from which decay score is calculated. Items at this value receive maximum relevance scores. |
|
|
Yes |
Distance or time at which relevance drops to the |
|
|
No |
Creates a "no-decay zone" around the |
|
|
No |
Score value at the |
|
Apply to standard vector search
After defining your decay ranker, you can apply it during search operations by passing it to the ranker
parameter:
# Use the decay function in standard vector search
results = milvus_client.search(
collection_name,
data=["search query"],
anns_field="vector_field",
limit=10,
output_fields=["document", "timestamp"], # Include the decay field in outputs to see values
ranker=decay_ranker, # Apply the decay ranker here
consistency_level="Strong"
)
Apply to hybrid search
Decay rankers can also be applied to hybrid search operations that combine multiple vector fields:
from pymilvus import AnnSearchRequest
# Define search requests for different vector fields
dense_request = AnnSearchRequest(
data=["search query"],
anns_field="dense_vector",
param={},
limit=20
)
sparse_request = AnnSearchRequest(
data=["search query"],
anns_field="sparse_vector",
param={},
limit=20
)
# Apply decay ranker to hybrid search
hybrid_results = milvus_client.hybrid_search(
collection_name,
[dense_request, sparse_request],
ranker=decay_ranker, # Same decay ranker works with hybrid search
limit=10,
output_fields=["document", "timestamp"]
)
In hybrid search, Milvus first finds the maximum similarity score from all vector fields, then applies the decay factor to that score.