Skip to main content

Using Momento Leaderboards

Momento Leaderboards is a first-class service with purpose-built APIs that supports leaderboards with tens of millions of items and rapid ingestion/querying/updates.

Leaderboard Client Methods


Create Leaderboard Client

To create and interact with leaderboards, you must first create a LeaderboardClient.

Parameters


Returns


  • PreviewLeaderboardClient object capable of creating new leaderboards and interacting with existing ones.
new PreviewLeaderboardClient({
configuration: LeaderboardConfigurations.Laptop.v1(),
credentialProvider: CredentialProvider.fromEnvironmentVariable('MOMENTO_API_KEY'),
});
info
Full example code and imports can be found here

Create a Leaderboard

Use a LeaderboardClient to create a leaderboard by specifying a cache and leaderboard name.

Parameters


  • cacheName - string: Which cache to create the leaderboard in.
  • leaderboardName - string: What to name the leaderboard.

Returns


  • Leaderboard object or Error
// You can create multiple leaderboards using the same leaderboard client
// but with different cache and leaderboard names
leaderboardClient.leaderboard(cacheName, 'momento-leaderboard');
leaderboardClient.leaderboard(cacheName, 'acorns-leaderboard');

// Leaderboard and cache names must be non-empty strings
try {
leaderboardClient.leaderboard(cacheName, ' ');
} catch (error) {
console.log('Expected error creating a leaderboard with invalid leaderboard name:', error);
}
info
Full example code and imports can be found here

Leaderboard Methods


Upsert elements

Inserts elements if they do not already exist in the leaderboard. Updates elements if they do already exist in the leaderboard. There are no partial failures; an upsert call will either succeed or fail.

Parameters


  • elements - Dictionary: Dictionary of (id, score) pairs to upsert.

    • id: integer
    • score: double
  • The id can be a player identifier, session identifier, browser identifier or any other kind of identifier you want to use for this scoreboard. The full unsigned 64 bit range is allowed here, between 0 and 2^63-1 inclusive.

  • An id can only appear in a leaderboard one time, meaning you can't have two scores for one player unless that player has two ids!

Returns


One of the following:

// Upsert a set of elements as a Map
const elements1: Map<number, number> = new Map([
[123, 100.0],
[234, 200.0],
[345, 300.0],
[456, 400.0],
]);
const result1 = await leaderboard.upsert(elements1);
switch (result1.type) {
case LeaderboardUpsertResponse.Success:
console.log('Successfully upserted elements to leaderboard');
break;
case LeaderboardUpsertResponse.Error:
console.log('Upsert error:', result1.message());
throw new Error(
`An error occurred while attempting to call upsert on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result1.errorCode()}: ${result1.message()}`
);
}

// Or upsert a set of elements as a Record
const elements2: Record<number, number> = {
567: 500,
678: 600,
789: 700,
890: 800,
};
const result2 = await leaderboard.upsert(elements2);
switch (result2.type) {
case LeaderboardUpsertResponse.Success:
console.log('Successfully upserted elements to leaderboard');
break;
case LeaderboardUpsertResponse.Error:
console.log('Upsert error:', result2.message());
throw new Error(
`An error occurred while attempting to call upsert on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result2.errorCode()}: ${result2.message()}`
);
}
info
Full example code and imports can be found here
Upsert is implemented as a batched operation, so for large leaderboards, you can upsert in batches of up to 8192 elements.
// To upsert a large number of elements, you must upsert
// in batches of up to 8192 elements at a time.
// This example shows how to paginate for a large value of `totalNumElements`, such as `20000`.
const elements = [...Array(totalNumElements).keys()].map(i => {
return {id: i + 1, score: i * Math.random()};
});
for (let i = 0; i < totalNumElements; i += 8192) {
// Create a Map containing 8192 elements at a time
const batch = new Map(elements.slice(i, i + 8192).map(obj => [obj['id'], obj['score']]));

// Then upsert one batch at a time until all elements have been ingested
const result = await leaderboard.upsert(batch);
switch (result.type) {
case LeaderboardUpsertResponse.Success:
break;
case LeaderboardUpsertResponse.Error:
console.log(`Error upserting batch [${i}, ${i + 8192})`);
break;
}
}
info
Full example code and imports can be found here

Fetch elements by score

Fetches elements that fall within the specified min and max scores.

Elements with the same score will be returned in alphanumerical order based on their ID (e.g. IDs of elements with the same score would be returned in the order [1, 10, 123, 2, 234, ...] rather than [1, 2, 10, 123, 234, ...]).

Parameters


Optional Parameters


  • minScore - double: Inclusive lower bound for the score range. Defaults to -inf.
  • maxScore - double: Exclusive upper bound for the score range. Defaults to +inf.
  • order - LeaderboardOrder enum: The order to fetch the elements in. Defaults to ascending, meaning 0 is the lowest-scoring rank.
  • offset - integer: The number of elements to skip before returning the first element. Defaults to 0.
  • count - integer: The maximum number of elements to return. Defaults to 8192.

Returns


One of the following:

// By default, FetchByScore will fetch the elements from the entire score range
// with zero offset in ascending order. It can return 8192 elements at a time.
const result1 = await leaderboard.fetchByScore();
switch (result1.type) {
case LeaderboardFetchResponse.Success:
console.log('Successfully fetched elements using open score range:');
result1.values().forEach(element => {
console.log(`\tId: ${element.id} | Rank: ${element.rank} | Score: ${element.score}`);
});
break;
case LeaderboardFetchResponse.Error:
throw new Error(
`An error occurred while attempting to call fetchByScore with no options on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result1.errorCode()}: ${result1.message()}`
);
}

// Example specifying all FetchByScore options. You can provide any subset of these options
// to modify your FetchByScore request.
const result2 = await leaderboard.fetchByScore({
minScore: 10,
maxScore: 600,
order: LeaderboardOrder.Descending,
offset: 2,
count: 10,
});
switch (result2.type) {
case LeaderboardFetchResponse.Success:
console.log('Successfully fetched elements by score using all options:');
result2.values().forEach(element => {
console.log(`\tId: ${element.id} | Rank: ${element.rank} | Score: ${element.score}`);
});
break;
case LeaderboardFetchResponse.Error:
throw new Error(
`An error occurred while attempting to call fetchByScore with all options on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result2.errorCode()}: ${result2.message()}`
);
}
info
Full example code and imports can be found here
FetchByScore is implemented as a batch operation, so for large leaderboards, you can fetch in batches of up to 8192 elements.

You can page through multiple elements that fall within the requested score range using the offset parameter until you receive an empty list, which indicates the end of the requested elements.

// Use the offset option to paginate through your results if your leaderboard
// has more than 8192 elements.
// This example shows how to paginate for a large value of `totalNumElements`, such as `20000`.
for (let offset = 0; offset < totalNumElements; offset += 8192) {
const result = await leaderboard.fetchByScore({offset});
switch (result.type) {
case LeaderboardFetchResponse.Success:
processBatch(result.values());
break;
case LeaderboardFetchResponse.Error:
console.log(
`Error fetching batch by score [${offset}, ${offset + 8192}) (${result.errorCode()}: ${result.message()})`
);
}
}
info
Full example code and imports can be found here

Fetch elements by rank

Fetches elements that fall within the specified min and max ranks.

Parameters


  • startRank - integer: Inclusive lower bound for the rank range. Defaults to 0.
  • endRank - integer: Exclusive upper bound for the rank range. Defaults to startRank + 8192.

Optional Parameters


  • order - LeaderboardOrder enum: The order to fetch the elements in. Defaults to ascending, meaning 0 is the lowest-scoring rank.

Returns


One of the following:

// By default, FetchByRank will fetch the elements in the range [startRank, endRank)
// in ascending order, meaning rank 0 is for the lowest score.
const result1 = await leaderboard.fetchByRank(0, 10);
switch (result1.type) {
case LeaderboardFetchResponse.Success:
console.log('Successfully fetched elements in rank range [0,10)');
result1.values().forEach(element => {
console.log(`\tId: ${element.id} | Rank: ${element.rank} | Score: ${element.score}`);
});
break;
case LeaderboardFetchResponse.Error:
throw new Error(
`An error occurred while attempting to call fetchByRank with no options on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result1.errorCode()}: ${result1.message()}`
);
}
info
Full example code and imports can be found here
For large leaderboards, you will need to fetch in batches of up to 8192 elements.
// Use the startRank and endRank options to paginate through your leaderboard
// if your leaderboard has more than 8192 elements
// This example shows how to paginate for a large value of `totalNumElements`, such as `20000`.
for (let rank = 0; rank < totalNumElements; rank += 8192) {
const result = await leaderboard.fetchByRank(rank, rank + 8192, {order: LeaderboardOrder.Descending});
switch (result.type) {
case LeaderboardFetchResponse.Success:
processBatch(result.values());
break;
case LeaderboardFetchResponse.Error:
console.log(
`Error fetching batch by rank [${rank}, ${rank + 8192}) (${result.errorCode()}: ${result.message()})`
);
}
}
info
Full example code and imports can be found here

Fetch elements by ID

Fetches elements given a list of element IDs.

Parameters


  • ids - List: List of integers representing the ids of the elements to fetch.

Optional Parameters


  • order - LeaderboardOrder enum: The order to fetch the elements in. Defaults to ascending, meaning 0 is the lowest-scoring rank.

Returns


One of the following:

// Provide a list of element IDs to get their ranks in ascending or descending order
const result = await leaderboard.getRank([123, 456, 789], {
order: LeaderboardOrder.Descending,
});
switch (result.type) {
case LeaderboardFetchResponse.Success:
console.log('Successfully fetched the rank of 3 elements:');
result.values().forEach(element => {
console.log(`\tId: ${element.id} | Rank: ${element.rank} | Score: ${element.score}`);
});
break;
case LeaderboardFetchResponse.Error:
throw new Error(
`An error occurred while attempting to call getRank on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}
info
Full example code and imports can be found here

Get leaderboard length

Gets the number of entries in the leaderboard. The leaderboard name is inferred from the Leaderboard object.

Parameters


Returns


One of the following:

const result = await leaderboard.length();
switch (result.type) {
case LeaderboardLengthResponse.Success:
console.log('Successfully retrieved leaderboard length:', result.length());
break;
case LeaderboardLengthResponse.Error:
throw new Error(
`An error occurred while attempting to call length on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}
info
Full example code and imports can be found here

Remove elements

Removes elements with the specified IDs.

Parameters


  • ids - List: A list of ids for the elements you want to remove.

Returns


One of the following:

// Provide a list of element IDs to delete those elements
const result = await leaderboard.removeElements([123, 456, 789]);
switch (result.type) {
case LeaderboardRemoveElementsResponse.Success:
console.log('Successfully removed elements');
break;
case LeaderboardRemoveElementsResponse.Error:
throw new Error(
`An error occurred while attempting to call removeElements on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}
info
Full example code and imports can be found here
For large leaderboards, you will need to remove in batches of up to 8192 elements.
// You can remove batches of 8192 elements at a time.
// This example shows how to paginate for a large value of `totalNumElements`, such as `20000`.
const ids = [...Array(totalNumElements).keys()];
for (let i = 0; i < totalNumElements; i += 8192) {
const result = await leaderboard.removeElements(ids.slice(i, i + 8192));
switch (result.type) {
case LeaderboardRemoveElementsResponse.Success:
break;
case LeaderboardRemoveElementsResponse.Error:
console.log(`Error removing batch [${i}, ${i + 8192}) (${result.errorCode()}: ${result.message()})`);
break;
}
}
info
Full example code and imports can be found here

Delete leaderboard

Deletes the leaderboard. The leaderboard name is inferred from the Leaderboard object.

Parameters


Returns


One of the following:

const result = await leaderboard.delete();
switch (result.type) {
case LeaderboardDeleteResponse.Success:
console.log('Successfully deleted the leaderboard');
break;
case LeaderboardDeleteResponse.Error:
throw new Error(
`An error occurred while attempting to call delete on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}
info
Full example code and imports can be found here