Saving multiple items Datastore Handling

Ok. So I’ve been scripting for 4 years now and I’ve been using the generic datastore system for a while now. My question is when it comes to saving multiple items in a datastore I know you have to either

A. Put in each values separately
or
B. Group them in tables

But is there a way to save a folder that has multiple values inside of it? For example say I had a configurations folder but I decided to put 5 values in the folder Ex. 5 NumberValues

Would I be able to just use something like :GetDescendants() or :GetChildren()? It doesn’t have to be those exact lines but I’m just wondering if you could do it that way without having 1000 lines of code for datastores.

I really do NOT suggest making multiple datastore just for storing 1 value. And instead of dictionary, have it an array.

How?

Let’s say I have to save Apple, Banana, Orange, Blueberry, and Mango, and how many there are. Instead of adding a key as the name/key and the amount as value, you will just do an array where there is a numerical index.

Not

{
    Apple = 1,
    Orange = 2,
    Mango = 9,
    Blueberries = 11,
    Banana = 3,
}

What I suggest

{
    1, -- numbers are the amount, not the numerical index
    2,
    9,
    11,
    3
}

You can just insert the values of the number values into a table. And then you can use the saved table to insert new number values when a player joins.

Just like @DeFunnyPerson said, You could get the Children inside, then loop through them, insert them one by one to an empty table & then save it to the dataStore for later use, you can also JsonEncode it before storing if you want to. Like this for example:

local saveTable = {}

for _, item in pairs(Folder:GetChildren()) do
     saveTable[item.Name] = item.Value --The item.Name will be the key used to access it now, and the value will now be assigned as the value of that NumberValue in the folder its currently iterating through.
end

DataStore:SetAsync(saveTable)

@Quwanterz How are you supposed to know which value is for which key when you want to load it next time the server accesses the datastore table?

1 Like

DataStores can save a string and an array. They cannot save dictionaries since they only accept UTF-8. So telling him not to save dictionaries but an array seem reluctant.

I recommend you use Dictionaries, it’s a very easy way to grab/save data.

local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local PlayerData = DataStoreService:GetDataStore("PlayerData")

Players.PlayerAdded:Connect(function(player) 
    — I recommend  that you create values in a different script

    local data = Instance.new("Configuration", player) 
    data.Name = "Data"

    local cash = Instance.new("IntValue", data)
    cash.Name = "Cash"
    local gems = Instance.new("IntValue", data)
    gems.Name = "Gems"

    local data = nil
    local success, err = pcall(function()
        PlayerData:GetAsync(player.UserId.."-data")
    end)

    if success then
  
        if data then
            — load data from that dictionary 
            cash.Value = data.Cash — gets the "Cash" key in the data dictionary.
            gems.Value = data.Gems

        else
            — set default values here, I recommend using a dictionary here as well
            cash.Value = 100
            gems.Value = 0

        end

    else

        warn("There was an error whilst grabbing data!")
        warn("Error", err)

    end

end)

Players.PlayerRemoving:Connect(function(player) 
        local currentData = player:WaitForChild("Data")
        local cash = currentData.Cash
        local gems = currentData.Gems

        local data = {
            Cash = cash.Value,
            Gems = gems.Value,
             — you can save a lot of values here
             — you can even do
             MoreData = {
                    SomeValue = 27, — and store even more if you’d like
             }
        }

        local success, err = pcall(function() 
            PlayerData:UpdateAsync(player.UserId.."-data", function() 
                return data
            end)
        end)

        if not success then
            warn("There was an error whilst saving data!")
            warn("Error:", err)
        end
end)

That’s a very clean solution of doing it. It also makes it very easy to grab data as well.

When I mean array, I mean numerical-index table. For example:

{
    "A", -- Index is 1 since it's at the top, A is the value.
    "B", -- Index is 2 since it's at the middle/2nd from the top, B is the value
    "C" -- Index is 3 since it is at the last/3rd from the top, C Is the value
}

While dictionary:

{
    ["A"] = "Apple",
    ["B"] = "Banana",
    ["C"] = "Cucumber"
}

I’m only using Roblox’s API logic and naming, so it may be confusing to others.

Why should you use an array over a dictionary though? Other than a performance difference, why should you use them?

The key also counts as a data, and there is a limit of 50 characters on a key. Since arrays only use numerical index, aka 1, 100, 1000, you don’t have to rename and you can have a number maximum of 1^50. (1 with 50 zerios)

This isn’t the case where you have to name the key, it’s just a person’s preference. I really don’t like naming every key, so I stick with arrays.

So basically in a key in a dictionary could only have 50 characters like this.

local dict =  {
    ["ajhfriifehhwihejwihwi"] = value — imagine the key is 50 characters
}

I still fail to see the point of using an array over a dictionary, later on in developments it’s gonna be pretty tough to keep track of every value you want to store.

local data = {
    Cash = 100
}

Dictionaries on the other hand are very easy to use, and grabbing data is as simple as dictionary.Key . In this example it’d be data.Cash.

As I said, it’s someone’s preferences. What I do is comment a line like this:

-- [[
    {
    "A" -- Position
    "B" -- Value
    "C" -- Highscore
    }
]]

In which I show where that value is.

I was using this before. This is what I was trying to avoid doing. Just by saving everything in a folder, but I guess I’m going to have to do it this way.