List all storage objects in a collection

Hello,

I’m trying to use nakama to get the number of times a level has been played.

I am using storage objects to store the number of plays.
The object is set with

Collection: LevelPlays,
Key: LevelName,
Value: {"Plays": \<Number of plays\>}

I need to populate the menu with the levels at runtime(since players can make new levels) and these menu objects need to show the play count on them.

Can I use the storage_list as a server RPC function to get all the play counts of all the levels and apply them to the menu objects?(Maybe something like concatenating the return value with all the play counts and separating them on the client side)

I noticed that there is a limit variable in the server_list server function. If I have more than 100 levels, how can I get across the limit? How do I use the cursor?

Listing operations are paginated to make sure you always get back only the required set of data, rather than get everything back and have to filter out a lot you may not need. Data is returned in “pages” and you can use cursors to get the next page or listing results.

Any non-nil cursor indicates there are more results beyond the current page. A nil cursor indicates your pagination has reached the end.

I’ll assume you want to paginate storage listings in an RPC function, try this:

local nk = require("nakama")

local function list_all(context, payload)
  local all_results = {}
  local next_cursor = nil
  repeat
    local results, cursor = nk.storage_list(nil, "LevelPlays", 100, next_cursor)
    for _, result in ipairs(results) do
      table.insert(all_results, result)
    end
    next_cursor = cursor
  until (not next_cursor)
  -- all_results now contains all records owned by the root user
  -- and that belong to collection "LevelPlays"

  return nk.json_encode(all_results)
end
nk.register_rpc(list_all, "list_all")

This is an example RPC function that will list all available records and return them, but you can of course just use the records internally in the RPC function rather than simply return them to the client/caller.

3 Likes

@zyro Same question, but in Unity. I can’t seem to figure out how to paginate the results to get more than 100. Here is my code:

var result = await client.ListUsersStorageObjectsAsync(session4, "events", session4.UserId, 100, null); 

Am I supposed to change the 5th value from null to something else, or what?

The result in your example should be a IApiStorageObjectList type. That exposes the resulting objects, and a cursor. If the cursor is not null/empty then there are more results you can fetch. Pass in the cursor as the 5th parameter in another identical call to get the next page of results.

1 Like

Thanks. I’m familiar with making PSQL queries, but new to the idea of using a cursor.
As an example, I’m looking to return all events in a month. I might do that using a query like:

select * from storage where create_time between '2020-06-01' and '2020-06-30';

Do I just make a string value with a PSQL query, and use that as my cursor?

Using cursors requires you to write queries in a specific pattern, and ensure the index you’re hitting with those queries is set up correctly to ensure a cursor points to a specific row and can therefore be used as a point from which to scan forward.

In your example you would want a composite index containing the create time and any other columns needed to uniquely identify that row. Note that if you’re trying to reference Nakama’s own storage table none of the existing indexes are suitable for that query.

You can find examples in Nakama’s own source code on how cursor queries might be constructed.

1 Like

Thanks @zyro. Looking at that GO example, it appears the query itself is defined on line 166? I’ve tried a few iterations of this in C#, but it gives an error every time that the cursor is invalid. Do you happen to have any examples that use cursors to query storage from Unity/C# instead of GO? If not, I can make a new Topic for it since it’s a little off from the original question.

@EarthAdam You’re right, it’s off topic for this thread. Please start a new thread and share both the server and client-side code you’re trying to use.

Okay, here’s a stab at it: Custom storage query in Unity
I think I only have client-side code in there though. What server side code are you looking for?