“ds:SetAsync(tostring(player.userId)…”:Stats", util.EncodeJSON(stats))"
You don’t need to do this. Get/Set/UpdateAsync automatically JSON Encode / Decode the value that you’re storing with them. You can just directly use them like so and it will work correctly:
ds:SetAsync('PlayerList$80119', {
Name = 'Stravant';
Id = 80119;
ListOfStuff = { ... };
})
“- you can’t have two different value types in a list”
I’m not sure what you mean by that. You can store whatever data you want in the DataStore, the only restriction is that you can’t have numeric indices and non-numeric keys in a table that you’re storing. (That is, the thing that you store has to be either an array or a map, but it cannot be both at the same time) And if you really need to store a table like that you can always flatten it like so before storing it, and expand it afterwards when reading it:
function flatten(tb)
local flat = {}
for k, v in pairs(tb) do
table.insert(flat, {k, v})
end
return flat
end
function expand(flat)
local tb = {}
for _, dat in pairs(flat) do
tb[dat[1]] = dat[2]
end
return tb
end
“- you can’t iterate through it unless it’s an OrderedDataStore”
This is a hard problem to solve. The issue is that most of the data stores will be too big to dump in a single request. If your database has 5000+ entries in it that’s too many to simply return to you and let you iterate over them, as your code would hang the server while you were trying to digest all of that data, as well as hurting the performance of the database by having it spit out all of that data. And there’s also the issue that you can’t dump the whole DB in a consistent state easily. It may take up to a few minutes to dump out the whole data store if you request that: What should your servers do during that time? Not be allowed to touch the data store? Because if they are allowed, you won’t be able to get out one consistent “snapshot” of the data, you’ll get half of the edits but not the other half that happened during the time that you were reading it.
“- you can’t findFirstChild one (DataStore:findFirstChild(“Dinizterz”)), I know you could just iterate through it but 1. Can only iterate if it’s an Ordered 2. Unnecessary work”
If you want both iteration and searching then you should use a combination of both an OrderedDataStore and a normal DataStore. For instane, you can have your normal data store, and an ordered data store:
Normal: userId -> {
score = ...;
name = ...;
id = ...;
}
Ordered: userId -> score
And when you update the score, update both the ordered data store, and the normal data store entries. That way you can get the scores by name, and also still show the top leaderboard entries by order.
“- DataStores can’t store Objects. (The only Object I ever save is a Value Object, I’m not saving maps or anything!)”"
You shouldn’t store objects. You should serialize out the data from your objects into a table, and store that in the data store. That way you can also reorganize the structure of your game objects in a game without “messing up” the data that’s currently in your data store, because you just have to change the serialization code that figures out how to turn your roblox objects into tables. EG:
function storeObjects(player)
DataStore:UpdateAsync('PlayerList$'..player.userId, function(oldValue)
oldValue = oldValue or {
score = 0;
kills = 0;
}
oldValue.score = oldValue.score + player.Round.Score.Value
oldValue.kills = oldValue.kills + player.Round.Kills.Value
return oldValue
end)
end)
And as for the original post, losing data: I’m almost certain that it’s a problem in your code. We’ve been using the data store for our internal games team game for months now and never seen data randomly get lost. Here’s some things that you can try looking into:
-
Make sure that your value-size that you’re storing isn’t too big. If you’re trying to store 100KB worth of stuff in a single key the data store will get corrupted and will no longer be able to read or write that key, it will always fail to be read, irreversibly. So you should be very careful if you’re storing unbounded lists (lists that may grow arbitrarily long) in the data store within a single key that they do not become too large. If you stay under 10KB worth of key then you should be safe.
-
Make sure that you’re only using SetAsync where you can afford for data to get lost. You should always be using UpdateAsync if the integrity of your data is very important. If multiple servers try to SetAsync on the same key at the same time then data can and will be lost. On the other hand UpdateAsync guarantees that nothing can go wrong with the update.
-
Make sure that you’re very careful with implementing “default” values. If you have a default value for some DataStored value you should be making very sure that there is definitely no way it can accidentally get stored back to a player’s data when they already have a non-default value there, or when they do something like leave the game before their initial loading of data has completed then they’ll lose data. (For instance, if you save on leave, and populate their data on loaded. The load can take an arbitrarily long amount of time until the data store responds with it’s value, if they leave before the loading values get back, and you save the default values that are still there for them at that time, then they’ve lost their data)
-
Make sure that your keys are by ID and not by name. Remember that people can change their names, and you don’t want people to lose data when they do so.