How to add a new table to a DataStore

  1. What do you want to achieve? I want to store the moderation logs for a user for my admin system. (For example, if someone gets warned, a new warn table is inserted in the player datastore, it contains the reason, the moderator who warned and other stuff)

  2. What is the issue? I don’t know how to insert a new table in a datastore

  3. What solutions have you tried so far? I tried to do it myself, and looked on forums

To make a DataStore itself, you use the DataStoreService, local moderationLogs = game:GetDataStore(WhateverYouNameIt) obviously importing the DataStore Service with game:GetService("DataStoreService")
Then you could use they key being the player’s UserId that’s being warned, then using a table and inserting it into another table, for example;

local userModerationLogs = {
}

make userModerationLogs include whatever is already saved used GetAsync on the Datastore you made

local newEntry = {}
newEntry[“Moderator”] = moderator.Name
newEntry[“ModeratorId”] = moderator.UserId
newEntry[“Reason”] = “Whatever the reason is”
newEntry[“Date”] = “Idk if you even want this.”

table.insert(userModerationLogs, newEntry)

Then SetAsync this back into the Datastore.

This is personally how I’d do it, you can also use a for loop to loop the table to get each item in the table.

Create a new index key:

Table[Player.UserId] = Data

Yo man I have a few questions about the method you stated above

Necro’ing a post is crazy work, especially after a year, but whats up I guess? how can i help?

It’s an issue which i cant really find around the dev forum, so like let’s put it like this:

local DataStoreService = game:GetService("DataStoreService")
local gameData = DataStoreService:GetDataStore("data")
local key = 1

local data = {{plr.Name, Action, tostring(os.date("%x"))}}

gameData:UpdateAsync(key, function()
return data
end)

Everything fine until here the data saves with no issues but How would I add a new table to the dictionary without overwriting the old data?
If I do print data, it prints normally and when I call a function to update data the old data gets overwritten by the new one.
I have tried many methods but none worked,

Here is an example:

-- Services
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")

-- DataStore
local ModerationDataStore = DataStoreService:GetDataStore("ModerationDataStore")

-- Function to add a new warning
local function addWarning(player, reason, moderator)
    local userId = player.UserId
    
    -- Retrieve existing warnings
    local success, existingData = pcall(function()
        return ModerationDataStore:GetAsync(userId)
    end)

    local warnings
    if success and existingData then
        warnings = existingData
    else
        warnings = {}  -- Initialize if no existing data
    end

    -- Create new warning entry
    local newWarning = {
        Reason = reason,
        Moderator = moderator,
        Time = os.date("!%Y-%m-%d %H:%M:%S")  -- Current time
    }

    -- Add the new warning to the list
    table.insert(warnings, newWarning)

    -- Save updated warnings back to DataStore
    local saveSuccess, errorMsg = pcall(function()
        ModerationDataStore:SetAsync(userId, warnings)
    end)

    if not saveSuccess then
        warn("Failed to save warnings for user " .. userId .. ": " .. errorMsg)
    end
end

-- Example usage
local player = Players:FindFirstChild("DangerRangerJJD")  -- Replace with actual player reference
if player then
    addWarning(player, "Inappropriate language", "ModeratorName")
end

1 Like

hi, refer to @DangerRangerJJD 's response. They explain it well, a lot better than I would’ve

Your system looks good, but you should probably use UpdateAsync instead of two seperate Get and Set requests. That way, there’s only one single point of failure, plus UpdateAsync has a few more safety features.

@K0_zzy was nearly there but forgot to make the data add on to already existing data.

local function addModLog(player: Player, action: string): (boolean, string?)
	local modData = {player.Name, action, tostring(os.date())}
	
	--or whatever key you use
	local key = "ModKey_"..player.UserId
	
	local success, result
	local attempt = 0
	
	repeat
		success, result = pcall(DataStore.UpdateAsync, DataStore, key, function(old)
			local data = old.ModerationData or {}
			table.insert(data, modData)
			old.ModerationData = data
		
			return old
		end)
		
		attempt += 1
	until
		success or attempt == 3
	
	if not success then
		warn("Failed to update moderation log")
	end
	
	return success, result
end

Or, since the Ban API has released after this post was created and if players are banned, just use the PrivateReason field on that.

2 Likes

I completely forgot about UpdateSync. Thank you for the reminder. I highly recommend using UpdateSync.

1 Like