Ranking Signals
The order in which the results are returned can be adjusted by leveraging the ranking signals syntax ranking_expr="<your-expression>"
. For a given search query, each object has a relevance score which determines the baseline ranking and can be modified with a ranking expression. This allows you to combine values available in your object store with the relevance score and perform mathematical or logical operations. The syntax can be as simple as ranking_expr="a + b + 1"
or as complex as you need.
Check out the ranking signals quickstart for an example: Quickstart: Ranking Signals
What are Signals?
Signals in search refer to data points or cues that indicate the relevance, quality, or context of content in relation to a user's query. They can include user behavior (e.g., clicks, dwell time), content features (e.g., keywords, metadata), or external factors (e.g., link popularity). These signals are used by search engines to rank results, personalize responses, and improve overall search accuracy. By leveraging a variety of signals, search engines can deliver more relevant and effective results to users.
Examples of Signals
- Content signals: Keywords, metadata, freshness or recency, price
- Engagement signals: Clicks, favorites/likes, dwell time
- User signals: Previous engagement, purchase history, location
Read more about how Google describes signals - https://www.google.com/search/howsearchworks/how-search-works/ranking-results/
How-To: Update ranking using Ranking Signals
Syntax
Syntax and keywords for "<your-expression>"
Operation | Description / Examples |
---|---|
uncalibrated_relevance (float) | the unmodified relevance score of the object |
object.<property> (varies) | the value of <property> for the object as defined in the object store. Nested fields can be accessed with the dot notation e.g. object.a.b.c |
NOW (float) | the current timestamp in unix time (seconds) |
timestamp(<timestamp>) (float) | function to convert a RFC 3339 <timestamp> string to unix time (seconds), e.g. timestamp("2015-11-03T15:01:00.05Z") |
Operators | ^ , * , / , % , + , - , if , etc. |
Functions | min , max , len , floor , etc. |
Value types | string , boolean , integer , float , tuple , empty |
Variables | foo = 1 |
Comments | // some comment |
See the "Supported Operations" page for more details
Important: The relevance is "uncalibrated" and is only meant to compare objects. The value does not have an intrinsic meaning; its distribution and bounds can vary depending on the evaluation method. We advise against using its value as a cutoff.
Important: The ranking signals are meant as nudges to improving the ordering of objects with otherwise similar relevance. If you find yourself using these signals to drastically modify the relevance score, you possibly have a larger problem that should be addressed at the source.
Examples
Simple Example
You created a value in your object store named promotion_boost
that has a value of 0 by default but can be set to 0.01 for objects that are being promoted. The following ranking expression:
uncalibrated_relevance + object.promotion_boost
would score the promoted items higher than similar items.
For another use case, you want to boost a specific brand that is on promotion and write the following expression:
uncalibrated_relevance * if(object.brandName == "SomeBrand", 1.01, 1.0)
so items belonging to "SomeBrand" will be scored 1% higher.
Rank by multiple fields
You can combine multiple fields in a single ranking expression to reward objects that contain either or both fields. In the below example, we have two fields: isBoosted and isActive. We want results that have these fields set to true
to be ranked higher. We can use a conditional expression to add a 1% boost when they are true
. If both fields are true, a 2% boost is applied. If only one field is true, a 1% boost is applied. If neither field is true, no boost is applied. This example can be expanded to more fields and different boost values depending on your use case.
uncalibrated_relevance * (if(object.isBoosted == true, 1.01, 1.0) * if(object.isActive == true, 1.01, 1.0))
Complex Example
You want to prioritize results that are both recent and relevant by using more advanced operations such mathematical functions and variables. You create the following ranking expression:
decay_time = 60 * 60 * 24; uncalibrated_relevance * (0.8 + 0.2 * math::exp(-(NOW - timestamp(object.details.timestamp)) / decay_time))
which uses the object's timestamp object.details.timestamp
to decay the uncalibrated_relevance
from 100% (now) to 87% (one day ago) to 80% (>few days ago) of its unmodified value. It also uses an exponential function math::exp
and the <variable> = <value>;
syntax to define a decay_time
of one day.