Custom Ranking

Stream allows you to configure your own ranking method. You can add multiple ranking methods to a given Flat feed group.

Ranked feeds are only available on Standard plans and higher. Contact support after upgrading your account to enable ranked feeds for your organization.

An example ranking config is shown below:

{
  "score": "decay_linear(time) * popularity ^ 0.5",
   "defaults": {
    "popularity": 1
  }
}

Available Functions

obs: functions are parsed in lowercase

namedescription
Basic ArithmeticThe following are supported: + - * / ( ) ^
ln(x)Log Function natural base
log(x)Log Function base 10
sin(x)Trigonometric sine function
cos(x)Trigonometric cosine function
tan(x)Trigonometric tangent function
abs(x)Absolute value
min(a,b)Minimum value
max(a,b)Maximum value
trunc(x)Truncates to the nearest integer value
round(x)Rounds to the nearest integer value
decay_linear(t)Linear Decay
decay_exp(t)Exponential Decay
decay_gauss(t)Gauss Decay
rand_normal()Returns a normally distributed number in the range [-inf, +inf] with standard normal distribution (stddev = 1, mean = 0)
rand_normal(a,b,σ,µ)Returns a normally distributed number in the range [a, b] with specific normal distribution (stddev = σ, mean = µ)
rand()Returns a random number in the range [0, 1.0)
rand(a,b)Returns a random number in the range [a, b)
to_unix_timestamp(t)Converts a time value to a unix timestamp
dist(lat1,lng1,lat2,lng2,unit)Returns the distance between the two points given by (lat1,lng1) and (lat2,lng2). By default the unit is in kilometers, but the unit can also be M for miles or N nautical miles. This function can be combined with the external ranking parameters to rank activities based on a users distance to them.

Operators

The scoring algorithm has support for simple control flows and logical operators.

  • Logical operators && and ||

  • Ternary conditional x ? y : z

  • Control order of evaluation with parens ()

This lets you construct a scoring algorithm like this

"score":"(a > 2 || (b > 4 && c > 3)) ? 1 : -1"

Adding Activities

Below is an example of how to add activities with custom ranking:

// Server-Side: Instantiate a feed using feed class 'user' and user id '1'
final user1 = client.flatFeed('user', '1');

// Client-Side: Instantiate a feed for feed group 'user', user id '1' and a security token generated server side
final user1 = client.flatFeed('user', '1', token);

// Add an activity to the feed - adding your ranking method as a parameter (in this case, "popularity"):
final activity2 = Activity(actor: 'User:2', verb: 'pin', object: 'Place:42', target: 'Board:1', extraData: {'popularity': 5});

// Add Activity 
await user1.addActivity(activity);

Retrieving Activities

Below is an example of how to retrieve activities sorted by custom ranking:

// Get activities sorted by rank (Ranked Feeds Enabled):
 final response = await userFeed.getActivities(limit: 5, ranking: "popularity");

You can only use limit and offset for pagination with custom ranking.

Configuring ranking can be complex. Feel free to reach out to support if you have questions.

More visibility into ranking variables

If you need to inspect your ranking variables at runtime this can be achieved like so

result = user_feed_1.get(ranking="activity_popularity", limit=5, withScoreVars=True)

Decay & Ranking

Stream supports a Linear, Exponential, and Gauss decay. For each decay function, we support 4 arguments: Origin, Scale, Offset, and Decay. You can pass either a timedelta string (such as 3d, 4w), or a numeric value.

Parameters

namedescriptiondefault
originThe best possible value. If the value is equal to the origin the decay function will return 1.now
scaleDetermines how quickly the score drops from 1.0 to the decay value. If the scale is set to “3d” the score will be equal to the decay value after 3 days.5d
offsetValues below the offset will start to receive a lower score.0
decayThe score that a value at scale distance from the origin should receive.0.5
directionleft, right or both. If right is specified only apply the decay for the right part of the graph.both

You can use s, m, h, d and w to specify seconds, minutes, hours, days and weeks respectively.

The example below defines a simple_gauss with the following params:

  • scale : 5 days

  • offset : 1 day

  • decay : 0.3 day

This means that an activity younger than 1 day (the offset) will return a score of 1. An activity that is exactly 6 days old (offset + scale) will get a score of 0.3 (the decay factor). The full JSON config is shown below:

{
 "functions": {
  "simple_gauss": {
   "base":"decay_gauss",
   "scale":"5d",
   "offset":"1d",
   "decay":"0.3"
  },
  "popularity_gauss": {
   "base":"decay_gauss",
   "scale":"100",
   "offset":"5",
   "decay":"0.5"
  }
 },
 "defaults": {
   "popularity": 1
 },
 "score":"simple_gauss(time)*popularity"
}

You can specify defaults for the variables you use. The example above sets popularity to 1 if it’s missing from the activity. We highly recommend setting up defaults to prevent errors when retrieving activities without these variables.

Custom ranking is only working on the last 1000 activities of the feed.

Configuring ranking can be complex. Feel free to reach out to support if you have questions!

Analytics & Reaction Counts

Analytics and Reaction Counts can be used in ranking easily, contact support to get them enabled.

{
 "defaults": {
   "analytics": {
    "view": 0
   },
   "reaction_counts": {
    "like": 0,
    "comment": 0
   }
 },
 "score":"simple_gauss(time)*(0.1*analytics.view+0.5*reaction_counts.like+reaction_counts.comment)"
}

In this example, we define defaults for activities that might be missing any analytics or reactions on it. Then, a linear combination of these numbers is adjusted according to passed time.

Reaction counts are cached for 30 minutes. Therefore, when using this as a ranking criteria, you can anticipate a small delay between when a new reaction is added / removed and the recalculation of the score of the activity.

© Getstream.io, Inc. All Rights Reserved.