CRUD Operations

Delete Operations

Remove documents from MongoDB collections

Delete Operations

Learn how to delete documents from MongoDB collections.

DeleteOne

Delete the first document matching a filter.

Syntax

local deletedCount = collection:DeleteOne(filter)

Parameters

  • filter (table): Query filter to match documents

Returns

  • number: Count of deleted documents (0 or 1)

Examples

local players = db:Collection("players")

-- Delete by unique identifier
local deleted = players:DeleteOne({
    steamid = "STEAM_0:1:12345678"
})

if deleted > 0 then
    print("Player deleted")
else
    print("Player not found")
end

-- Delete first matching document
players:DeleteOne({ banned = true })

-- Delete by _id
players:DeleteOne({ _id = "ObjectId(...)" })

DeleteMany

Delete all documents matching a filter.

Syntax

local deletedCount = collection:DeleteMany(filter)

Parameters

  • filter (table): Query filter to match documents

Returns

  • number: Count of deleted documents

Examples

local players = db:Collection("players")

-- Delete all banned players
local deleted = players:DeleteMany({ banned = true })
print("Removed", deleted, "banned players")

-- Delete inactive players (30 days)
local thirtyDaysAgo = os.time() - (30 * 24 * 60 * 60)
local cleaned = players:DeleteMany({
    last_login = { ["$lt"] = thirtyDaysAgo }
})
print("Cleaned up", cleaned, "inactive accounts")

-- Delete all documents (BE CAREFUL!)
local all = players:DeleteMany({})
print("Deleted all", all, "players")

Warning: DeleteMany({}) with an empty filter will delete ALL documents in the collection!

Async Delete Operations

DeleteOneAsync

collection:DeleteOneAsync(
    { steamid = "STEAM_0:1:12345" },
    function(err, deletedCount)
        if err then
            print("Delete error:", err)
        elseif deletedCount > 0 then
            print("Player deleted")
        else
            print("Player not found")
        end
    end
)

DeleteManyAsync

collection:DeleteManyAsync(
    { banned = true },
    function(err, deletedCount)
        if err then
            print("Delete error:", err)
        else
            print("Removed", deletedCount, "banned players")
        end
    end
)

Delete Patterns

Safe Delete with Confirmation

function DeletePlayer(steamid, confirm)
    if not confirm then
        print("Please confirm deletion by passing true as second argument")
        return false
    end

    local players = db:Collection("players")
    local deleted = players:DeleteOne({ steamid = steamid })

    return deleted > 0
end

-- Usage
DeletePlayer("STEAM_0:1:12345", true)

Soft Delete Pattern

Instead of actually deleting, mark as deleted:

function SoftDeletePlayer(steamid)
    local players = db:Collection("players")

    players:UpdateOne(
        { steamid = steamid },
        {
            ["$set"] = {
                deleted = true,
                deleted_at = os.time()
            }
        }
    )
end

function RestorePlayer(steamid)
    local players = db:Collection("players")

    players:UpdateOne(
        { steamid = steamid },
        {
            ["$unset"] = {
                deleted = "",
                deleted_at = ""
            }
        }
    )
end

-- Query non-deleted players
function GetActivePlayers()
    local players = db:Collection("players")
    return players:Find({
        deleted = { ["$ne"] = true }
    })
end

Archive Before Delete

function ArchiveAndDelete(steamid)
    local players = db:Collection("players")
    local archive = db:Collection("players_archive")

    -- Get player data
    local player = players:FindOne({ steamid = steamid })
    if not player then
        return false, "Player not found"
    end

    -- Archive it
    player.archived_at = os.time()
    archive:InsertOne(player)

    -- Delete original
    players:DeleteOne({ steamid = steamid })

    return true, "Player archived and deleted"
end

Practical Examples

Player Deletion

function DeletePlayerAccount(steamid, reason)
    local players = db:Collection("players")
    local logs = db:Collection("deletion_logs")

    -- Get player before deletion
    local player = players:FindOne({ steamid = steamid })
    if not player then
        return false, "Player not found"
    end

    -- Log the deletion
    logs:InsertOne({
        steamid = steamid,
        username = player.username,
        reason = reason,
        deleted_at = os.time(),
        player_data = player  -- Store full data for audit
    })

    -- Delete the player
    local deleted = players:DeleteOne({ steamid = steamid })

    if deleted > 0 then
        return true, "Account deleted"
    else
        return false, "Deletion failed"
    end
end

Cleanup Old Data

function CleanupOldLogs(daysToKeep)
    local logs = db:Collection("logs")

    local cutoff = os.time() - (daysToKeep * 24 * 60 * 60)
    local deleted = logs:DeleteMany({
        timestamp = { ["$lt"] = cutoff }
    })

    print("Cleaned up", deleted, "old log entries")
    return deleted
end

function CleanupExpiredSessions()
    local sessions = db:Collection("sessions")

    local deleted = sessions:DeleteMany({
        expires_at = { ["$lt"] = os.time() }
    })

    print("Removed", deleted, "expired sessions")
    return deleted
end

Ban System

function BanPlayer(steamid, reason, duration)
    local players = db:Collection("players")
    local bans = db:Collection("bans")

    -- Record the ban
    bans:InsertOne({
        steamid = steamid,
        reason = reason,
        banned_at = os.time(),
        expires_at = duration and (os.time() + duration) or nil,
        permanent = duration == nil
    })

    -- Update player
    players:UpdateOne(
        { steamid = steamid },
        { ["$set"] = { banned = true } }
    )
end

function UnbanPlayer(steamid)
    local players = db:Collection("players")
    local bans = db:Collection("bans")

    -- Remove ban record
    bans:DeleteOne({ steamid = steamid })

    -- Update player
    players:UpdateOne(
        { steamid = steamid },
        { ["$set"] = { banned = false } }
    )
end

function CleanupExpiredBans()
    local players = db:Collection("players")
    local bans = db:Collection("bans")

    -- Find expired bans
    local expiredBans = bans:Find({
        expires_at = { ["$lt"] = os.time() },
        permanent = false
    })

    -- Unban each player
    for _, ban in ipairs(expiredBans) do
        players:UpdateOne(
            { steamid = ban.steamid },
            { ["$set"] = { banned = false } }
        )
    end

    -- Delete expired ban records
    local deleted = bans:DeleteMany({
        expires_at = { ["$lt"] = os.time() },
        permanent = false
    })

    print("Processed", deleted, "expired bans")
end

Inventory Item Removal

function ConsumeItem(steamid, itemId)
    local players = db:Collection("players")

    -- Remove item from inventory (using $pull)
    players:UpdateOne(
        { steamid = steamid },
        { ["$pull"] = { inventory = { id = itemId } } }
    )
end

function ClearInventory(steamid)
    local players = db:Collection("players")

    players:UpdateOne(
        { steamid = steamid },
        { ["$set"] = { inventory = {} } }
    )
end

Scheduled Cleanup

-- Run daily cleanup tasks
function DailyCleanup()
    print("Starting daily cleanup...")

    -- Clean old logs (keep 30 days)
    local logsDeleted = CleanupOldLogs(30)

    -- Clean expired sessions
    local sessionsDeleted = CleanupExpiredSessions()

    -- Process expired bans
    CleanupExpiredBans()

    print(string.format(
        "Cleanup complete: %d logs, %d sessions removed",
        logsDeleted, sessionsDeleted
    ))
end

-- Schedule with timer (Garry's Mod)
timer.Create("DailyCleanup", 24 * 60 * 60, 0, DailyCleanup)

Best Practices

  1. Always use filters: Never delete without specific criteria
  2. Log deletions: Keep audit trail for important data
  3. Consider soft delete: Mark as deleted instead of removing
  4. Backup before mass delete: Especially for DeleteMany
  5. Use async for non-critical: Cleanup tasks can be async
  6. Test filters with Find first: Verify what will be deleted
-- Test before delete
local toDelete = collection:Find({ status = "expired" })
print("Will delete", #toDelete, "documents")
-- collection:DeleteMany({ status = "expired" })

Next Steps