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


configuration - LeaderboardConfiguration


credentialProvider - CredentialProvider


Optional Parameters


Returns


PreviewLeaderboardClient object capable of creating new leaderboards and interacting with existing ones.

new PreviewLeaderboardClient({
configuration: LeaderboardConfigurations.Laptop.v1(),
credentialProvider: CredentialProvider.fromEnvironmentVariable({
environmentVariableName: 'MOMENTO_API_KEY',
}),
});

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

Optional Parameters


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);
}

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.

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);
if (result instanceof LeaderboardUpsert.Error) {
console.log(`Error upserting batch [${i}, ${i + 8192})`);
}
}

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!


Optional Parameters


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);
if (result1 instanceof LeaderboardUpsert.Success) {
console.log('Successfully upserted elements to leaderboard');
} else if (result1 instanceof LeaderboardUpsert.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);
if (result2 instanceof LeaderboardUpsert.Success) {
console.log('Successfully upserted elements to leaderboard');
} else if (result2 instanceof LeaderboardUpsert.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()}`
);
}

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, ...]).

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});
if (result instanceof LeaderboardFetch.Success) {
processBatch(result.values());
} else if (result instanceof LeaderboardFetch.Error) {
console.log(
`Error fetching batch by score [${offset}, ${offset + 8192}) (${result.errorCode()}: ${result.message()})`
);
}
}

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

  • Enum values: Ascending, Descending

  • 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.

  • Note: this is not the score of the first element to return, but the number of elements of the result set to skip before returning the first element.


count - integer

  • The maximum number of elements to return. Defaults to 8192, which is the maximum that can be fetched per request.

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();
if (result1 instanceof LeaderboardFetch.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}`);
});
} else if (result1 instanceof LeaderboardFetch.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,
});
if (result2 instanceof LeaderboardFetch.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}`);
});
} else if (result2 instanceof LeaderboardFetch.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()}`
);
}

Fetch elements by rank

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

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});
if (result instanceof LeaderboardFetch.Success) {
processBatch(result.values());
} else if (result instanceof LeaderboardFetch.Error) {
console.log(
`Error fetching batch by rank [${rank}, ${rank + 8192}) (${result.errorCode()}: ${result.message()})`
);
}
}

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

  • Enum values: Ascending, Descending

  • 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);
if (result1 instanceof LeaderboardFetch.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}`);
});
} else if (result1 instanceof LeaderboardFetch.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()}`
);
}

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

  • Enum values: Ascending, Descending

  • 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,
});
if (result instanceof LeaderboardFetch.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}`);
});
} else if (result instanceof LeaderboardFetch.Error) {
throw new Error(
`An error occurred while attempting to call getRank on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}

Get leaderboard length

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

Parameters


Optional Parameters


Returns


One of the following:

const result = await leaderboard.length();
if (result instanceof LeaderboardLength.Success) {
console.log('Successfully retrieved leaderboard length:', result.length());
} else if (result instanceof LeaderboardLength.Error) {
throw new Error(
`An error occurred while attempting to call length on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}

Remove elements

Removes elements with the specified IDs.

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));
if (result instanceof LeaderboardRemoveElements.Error) {
console.log(`Error removing batch [${i}, ${i + 8192}) (${result.errorCode()}: ${result.message()})`);
}
}

Parameters


ids - List

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

Optional Parameters


Returns


One of the following:

// Provide a list of element IDs to delete those elements
const result = await leaderboard.removeElements([123, 456, 789]);
if (result instanceof LeaderboardRemoveElements.Success) {
console.log('Successfully removed elements');
} else if (result instanceof LeaderboardRemoveElements.Error) {
throw new Error(
`An error occurred while attempting to call removeElements on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}

Delete leaderboard

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

Parameters


Optional Parameters


Returns


One of the following:

const result = await leaderboard.delete();
if (result instanceof LeaderboardDelete.Success) {
console.log('Successfully deleted the leaderboard');
} else if (result instanceof LeaderboardDelete.Error) {
throw new Error(
`An error occurred while attempting to call delete on leaderboard 'momento-leaderboard' in cache '${cacheName}': ${result.errorCode()}: ${result.message()}`
);
}