I have an OrderedDataStore that keeps track of every player’s wins value. I want to find out a player’s rank regardless of what “page” they are on. How could I do this? Would I have to find some tacky method to make the Page Size the number of entries in said OrderedDataStore? How would I do that?
Just use GetAsync
. An OrderedDataStore
is just like a regular data store except it has the ability to sort the keys.
I’ve tried that. Rather then returning the player’s rank (the index that the player is at in the OrderedDataStore), it returns the data.value
for that entry
For instance, if the player is in 1st place in the OrderedDataStore with, say, 12 wins, it would return 12. No matter what page the data is on, I want it to return the rank. The player could be in rank 500,000 and have 2 wins and I would still want it to return 500,000.
Oh that’s what you meant. You could loop through the pages with a function until the script is able to find the data for the given player on that page
What would that code look like though? Is there a way to definitively get the number of pages for a for
loop?
Have you tried requesting a page size with the pagesize as math.huge()
. Probably a terrible idea but I’m just throwing the idea out there. Sorta surprised there isn’t a function or sorts for this since I feel like my method is super hacky and probably won’t work at full scale.
Basically, when you’re getting the OrderedDataStore
, use the GetCurrentPage
function to get all the data on that page with a for
loop. If the player’s data wasn’t found then use the AdvanceToNextPageAsync
function and do it over again
Sorry, I prematurely marked your post as the solution. This code is giving me an error:
local rankList = leaderboardDatastore:GetSortedAsync(false, 10)
repeat
local page = rankList:GetCurrentPage()
for plrRank, data in pairs(page) do
print(data.key, player.UserId, rank)
if tonumber(data.key) == tonumber(player.UserId) then
rank = plrRank
end
end
if rank ~= nil then
rankList:AdvanceToNextPageAsync()
end
wait()
until rank ~= nil
“No pages to advance to”
By the way, “leaderboardDatastore” is just the OrderedDataStore.
AdvanceToNextPageAsync
can fail if there are no more pages to advance to. To combat this, you have to wrap it in a pcall
local rankList = leaderboardDatastore:GetSortedAsync(false, 10)
local function GetPlayerRank(player) : number | nil
local page = rankList:GetCurrentPage()
for plrRank, data in ipairs(page) do -- you should use ipairs for numerical tables (arrays) which GetCurrentPage returns
print(data.key, player.UserId, rank)
if tonumber(data.key) == tonumber(player.UserId) then
return plrRank -- returns the player's rank
end
end
local advanced, err = pcall(function()
rankList:AdvanceToNextPageAsync()
end)
if not advanced then
return warn("Unable to advance to next page:", err) -- returns nil
end
return GetPlayerRank(player) -- does the function again
end
Thank you! It works like a charm now.
cc @NickIsANuke
Note that you could also use .IsFinished
before :AdvanceToNextPageAsync
to prevent unnecessary calls. You should still use pcall
as :AdvanceToNextPageAsync
is a network call and can fail, but not for detecting if you’re on the final page.
Reference:
Sorry to revive this topic. But I was working exact same situation where I was trying to retrieve what would be the “rank” of an entry from an ordered datastore. While I had no issues with sifting through all the pages. I have to wonder the consequences and request budget usage when the rank of the player entry is massively low/high. It would be extremely beneficial performance and budget wise if there was a way to grab an index value while accessing an entry directly say by using a regular GetAsync() call with the OrderedDataStore. Does anyone know how to achieve that or are we stuck sifting through potentially 100s of thousands of entries until we find the index among the pages?