Could I use Embedded Tables to create a Datastore to save multiple tables of data to one key?

Hello developers! In my quest to become much better with datastores there is a question I often ponder, and that question is: Can you save multiple tables in a datastore to a single key?
Now, the reason I would like to do this is so I can I reduce the usage of :GetAsync() and :SetAsync() so I don’t put too much pressure on the datastore. I wanna be efficient with how I am saving the data. If using embedded tables is inefficient/a very horrible idea, then I am fine with that. That is after all why I am asking that question right now.

So, my problem would be wondering if multiple tables can be saved to a single key of a datastore to be more efficient with how often I am using :GetAsnyc() and :SetAsync().

To try and solve this problem I took to the Dev Forum initially. I searched to try and find any posts about the topic, and from what Is searched there appears to be nothing.
I also decided to try making my own script seeing if I could do it on my own.
Here is my very scuffed script:

local dataStoreService = game:GetService("DataStoreService")

local players = game:GetService("Players")

local dataStore = dataStoreService:GetDataStore("TestData")

local data = {
	leaderstats = {
		["ValueType"] = "NumberValue",
		
		["ParentFolder"] = "leaderstats",
		
		["Strength"] = 0,
		
		["Coins"] = 0,
		
		["Gems"] = 0,
		
		["Rebirths"] = 0
	},
	
	MultiplierData = {
		["ValueType"] = "NumberValue",
		
		["ParentFolder"] = "MultiplierData",
		
		["RebirthStrengthMultiplier"] = 1,
		
		["RebirthCoinsMultiplier"] = 1,
		
		["RebirthGemMultiplier"] = 1,
		
		["PetStrengthMultiplier"] = 0,
		
		["PetCoinsMultiplier"] = 0,
		
		["PetGemMultiplier"] = 0
	},
	
	EquippedItems = {
		["ValueType"] = "StringValue",
		
		["EquippedSword"] = "SwordName",
		
		["ParentFolder"] = "EquippedItems",
		
		["PetSlot1"] = "",
		
		["PetSlot2"] = "",
		
		["PetSlot3"] = "",
		
		["PetSlot4"] = "",

		["PetSlot5"] = "",
		
		["PetSlot6"] = "",
		
		["PetSlot7"] = "",
		
		["PetSlot8"] = "",
		
		["PetSlot9"] = "",
		
		["PetSlot10"] = ""
	},
	
	PurchasedSwords = {
		["ValueType"] = "BoolValue",
		
		["ParentFolder"] = "PurchasedSwords",
		
		["Sword1"] = true,
		
		["Sword2"] = false,
		
		["Sword3"] = false
	}
}

game.Players.PlayerAdded:Connect(function(player)
	local dataFromStore = nil
	
	local leaderstats = Instance.new("Folder")
	leaderstats.Name = "leaderstats"
	leaderstats.Parent = player
	
	local multiplierData = Instance.new("Folder")
	multiplierData.Name = "MultiplierData"
	multiplierData.Parent = player
	
	local equippedItems = Instance.new("Folder")
	equippedItems.Name = "EquippedItems"
	equippedItems.Parent = player
	
	local purchasedSwords = Instance.new("Folder")
	purchasedSwords.Name = "PurchasedSwords"
	purchasedSwords.Parent = player
	
	--If this becomes a hassel I will separate it into 4 different tables to assign data to. Let's hope this loop ages like wine and not milk -Exodia
	for _, embeddedTable in pairs(data) do
		for name, value in pairs(embeddedTable) do
			if name ~= "ValueType" and name ~= "ParentFolder" then
				local valueToMake = embeddedTable.ValueType
				
				local new = Instance.new(tostring(valueToMake)) 
				
				new.Name = name
				
				new.Value = value
				
				new.Parent = player:FindFirstChild(embeddedTable.ParentFolder)
			end
		end
	end
	
	local success, err = pcall(function()
		print("Retrieving Data")
		dataFromStore = dataStore:GetAsync("uid-".. player.UserId)
	end)
	
	if success then
		print("Getting PlayerData for: ".. player.Name ..", ID: ".. player.UserId)
		if dataFromStore then
			for _, folder in pairs(player:GetChildren()) do
				for name, value in pairs(dataFromStore) do
					if folder[name] ~= nil then
						folder[name].Value = value --This feels scuffed AF but it will hopefully work
					end
				end
			end
			print("Data (Hopefully) Loaded for: ".. player.Name ..", ID: ".. player.UserId)
		else
			print("Creating new PlayerData for: ".. player.Name ..", ID: ".. player.UserId)
		end
	else
		warn("An error occurred while loading PlayerData. Please Contact a Developer incase data is lost.")
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local dataForStore = {
		leaderstats = {},
		
		MultiplierData = {},
		
		EquippedItems = {},
		
		PurchasedItems = {}
	}
	
	--I am doing separate loops for each table of data to be safe
	for name, value in pairs(player.leaderstats:GetChildren()) do
		dataForStore.leaderstats[value.Name] = value.Value
	end
	
	for name, value in pairs(player.MultiplierData:GetChildren()) do
		dataForStore.MultiplierData[value.Name] = value.Value
	end
	
	for name, value in pairs(player.EquippedItems:GetChildren()) do
		dataForStore.EquippedItems[value.Name] = value.Value
	end
	
	for name, value in pairs(player.PurchasedSwords:GetChildren()) do
		dataForStore.PurchasedItems[value.Name] = value.Value
	end
	
	local success, err = pcall(dataStore.SetAsync, dataStore, "uid-".. player.UserId, dataForStore)

	if success then
		print("Successfully Saved Data for: "..player.Name)
	end
end)

I am using some sample data from a simulator game I am currently scripting. I wanted to test out the idea of using embedded tables to see if I could make an efficient method of saving data for my group’s game. Feel free to judge and critique however you’d like.

4 Likes

I have been wondering about that too, I have a lot of keys and someone recommend I change them to tables, but I was a little uncertain how to do that

A way that you could save and get in a easy way, is to simply just use HttpService and JsonEncode the entire table. And then decode the data when need be

1 Like

Is there somewhere I can go to learn more about that kind of stuff? I don’t have too much experience with using Http service and JsonEncode but if I could use these to create a better datastore I would like to learn more. I know the API will have stuff on them, but are there any other sources I can look at as well?

I can provide some code examples if you still need help.

1 Like

yeah, only because I wanna see how you’d use it in a data store. Then I can apply that to my script when I wake up. I like looking at the api references a lot but sometimes I need a few more examples with more advanced topics such as this

local Clans = {
    ["Cool Clan"] = {
        ["RobloxUser1"] = true,
        ["CoolUser1"] = true,
    },
    ["Amazing Clan"] = {
        ["RobloxUser2"] = true,
        ["BigGuy"] = true,
    },
    ["The Bois Clan"] = {
        ["OopWoop"] = true,
        ["YesSir"] = true,
    }
}

local Jsond = game:GetService("HttpService"):JSONEncode(Clans);
game:GetSerivce("DataStoreService"):SetAsync("Clans", Jsond);
warn(Jsond);
--> {"Amazing Clan":{"BigGuy":true,"RobloxUser2":true},"The Bois Clan":{"OopWoop":true,"YesSir":true},"Cool Clan":{"CoolUser1":true,"RobloxUser1":true}}

-------------------------------

local JsonClans = game:GetSerivce("DataStoreService"):GetAsync("Clans");
local Clans = game:GetService("HttpService"):JSONDecode(Clans);
warn(Clans)
-->  
{
    ["Amazing Clan"] =  ▼  {
        ["BigGuy"] = true,
        ["RobloxUser2"] = true
    },
        ["Cool Clan"] =  ▼  {
        ["CoolUser1"] = true,
        ["RobloxUser1"] = true
    },
        ["The Bois Clan"] =  ▼  {
        ["OopWoop"] = true,
        ["YesSir"] = true
    }
}

The → means what gets warned in the console

2 Likes

Thank you so much! I really appreciate this!
I will readjust my script accordingly in the morning as I have to go to bed for school.

1 Like

Check above, I sent a solution!

1 Like

If you need any more help, pm me :slight_smile:

Alright! Have a nice rest of your day :slight_smile:

Oh ok NICE, thank you this is very helpful!