CRUD Operations

Update Operations

Modify existing documents in MongoDB

Update Operations

Learn how to update documents in MongoDB collections.

UpdateOne

Update the first document matching a filter.

Syntax

local modifiedCount = collection:UpdateOne(filter, update [, upsert])

Parameters

  • filter (table): Query filter to match documents
  • update (table): Update operations to apply
  • upsert (boolean, optional): Create document if none match (default: false)

Returns

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

Examples

local players = db:Collection("players")

-- Basic update
local modified = players:UpdateOne(
    { steamid = "STEAM_0:1:12345" },
    { ["$set"] = { level = 10 } }
)
print("Modified:", modified, "document(s)")

-- Update multiple fields
players:UpdateOne(
    { steamid = "STEAM_0:1:12345" },
    {
        ["$set"] = {
            level = 15,
            last_login = os.time(),
            username = "NewName"
        }
    }
)

-- Increment a value
players:UpdateOne(
    { steamid = "STEAM_0:1:12345" },
    { ["$inc"] = { credits = 100 } }
)

-- Upsert (insert if not exists)
players:UpdateOne(
    { steamid = "STEAM_0:1:99999" },
    {
        ["$set"] = {
            username = "NewPlayer",
            level = 1
        }
    },
    true  -- upsert = true
)

UpdateMany

Update all documents matching a filter.

Syntax

local modifiedCount = collection:UpdateMany(filter, update [, upsert])

Parameters

  • filter (table): Query filter to match documents
  • update (table): Update operations to apply
  • upsert (boolean, optional): Create document if none match (default: false)

Returns

  • number: Count of modified documents

Examples

local players = db:Collection("players")

-- Update all players of a class
local modified = players:UpdateMany(
    { class = "Warrior" },
    { ["$inc"] = { strength = 5 } }
)
print("Modified:", modified, "warriors")

-- Reset all inactive players
local reset = players:UpdateMany(
    { last_login = { ["$lt"] = os.time() - (30 * 24 * 60 * 60) } },
    {
        ["$set"] = {
            active = false,
            vacation_mode = true
        }
    }
)
print("Marked", reset, "players as inactive")

-- Give bonus to all VIP players
players:UpdateMany(
    { vip = true },
    { ["$inc"] = { credits = 1000 } }
)

Update Operators

$set - Set Field Values

-- Set single field
{ ["$set"] = { level = 10 } }

-- Set multiple fields
{ ["$set"] = {
    level = 10,
    experience = 5000,
    last_updated = os.time()
}}

-- Set nested field
{ ["$set"] = { ["stats.kills"] = 100 } }

$inc - Increment Values

-- Increment by positive value
{ ["$inc"] = { credits = 100 } }

-- Decrement (negative value)
{ ["$inc"] = { credits = -50 } }

-- Multiple increments
{ ["$inc"] = {
    kills = 1,
    experience = 100,
    credits = 50
}}

$unset - Remove Fields

-- Remove a field
{ ["$unset"] = { temporary_buff = "" } }

-- Remove multiple fields
{ ["$unset"] = {
    old_field = "",
    deprecated_data = ""
}}

$push - Add to Array

-- Add item to array
{ ["$push"] = { inventory = "sword" } }

-- Add multiple items
{ ["$push"] = {
    inventory = { ["$each"] = { "sword", "shield", "potion" } }
}}

$pull - Remove from Array

-- Remove specific value
{ ["$pull"] = { inventory = "broken_sword" } }

-- Remove matching condition
{ ["$pull"] = { inventory = { rarity = "common" } } }

$addToSet - Add Unique to Array

-- Add only if not exists
{ ["$addToSet"] = { achievements = "first_kill" } }

-- Multiple unique values
{ ["$addToSet"] = {
    tags = { ["$each"] = { "vip", "beta_tester" } }
}}

Combined Operators

-- Multiple operations in one update
collection:UpdateOne(
    { steamid = "STEAM_0:1:12345" },
    {
        ["$set"] = {
            last_login = os.time(),
            online = true
        },
        ["$inc"] = {
            login_count = 1,
            credits = 10
        },
        ["$push"] = {
            login_history = os.time()
        }
    }
)

Async Update Operations

UpdateOneAsync

collection:UpdateOneAsync(
    { steamid = "STEAM_0:1:12345" },
    { ["$inc"] = { credits = 100 } },
    function(err, modifiedCount)
        if err then
            print("Update error:", err)
        else
            print("Modified:", modifiedCount)
        end
    end
)

UpdateManyAsync

collection:UpdateManyAsync(
    { active = true },
    { ["$inc"] = { daily_bonus = 50 } },
    function(err, modifiedCount)
        if err then
            print("Update error:", err)
        else
            print("Gave bonus to", modifiedCount, "players")
        end
    end
)

Practical Examples

Player Login

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

    players:UpdateOne(
        { steamid = steamid },
        {
            ["$set"] = {
                last_login = os.time(),
                online = true
            },
            ["$inc"] = {
                login_count = 1
            }
        }
    )
end

Level Up System

function LevelUpPlayer(steamid, experienceGained)
    local players = db:Collection("players")

    -- Get current player
    local player = players:FindOne({ steamid = steamid })
    if not player then return false end

    local newExp = player.experience + experienceGained
    local newLevel = player.level
    local expRequired = newLevel * 1000  -- Simple formula

    while newExp >= expRequired do
        newExp = newExp - expRequired
        newLevel = newLevel + 1
        expRequired = newLevel * 1000
    end

    -- Update with new values
    players:UpdateOne(
        { steamid = steamid },
        {
            ["$set"] = {
                level = newLevel,
                experience = newExp
            }
        }
    )

    return newLevel > player.level  -- Return if leveled up
end

Inventory Management

function AddItemToInventory(steamid, item)
    local players = db:Collection("players")

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

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

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

function AddAchievement(steamid, achievementId)
    local players = db:Collection("players")

    -- Only adds if not already present
    players:UpdateOne(
        { steamid = steamid },
        { ["$addToSet"] = { achievements = achievementId } }
    )
end

Bulk Updates

function DailyReset()
    local players = db:Collection("players")

    -- Reset daily challenges for all players
    local modified = players:UpdateMany(
        {},  -- All players
        {
            ["$set"] = {
                daily_challenges_complete = 0,
                last_daily_reset = os.time()
            }
        }
    )

    print("Reset daily challenges for", modified, "players")
end

function ApplyEventBonus(eventMultiplier)
    local players = db:Collection("players")

    -- Give event bonus to active players
    players:UpdateMany(
        {
            last_login = { ["$gte"] = os.time() - (24 * 60 * 60) }
        },
        {
            ["$inc"] = { event_tokens = 100 * eventMultiplier }
        }
    )
end

Upsert Pattern

Create or update in a single operation:

function SavePlayerStats(steamid, stats)
    local players = db:Collection("players")

    players:UpdateOne(
        { steamid = steamid },
        {
            ["$set"] = {
                stats = stats,
                updated_at = os.time()
            },
            ["$setOnInsert"] = {
                created_at = os.time(),
                steamid = steamid
            }
        },
        true  -- upsert
    )
end

Best Practices

  1. Use specific filters: Avoid updating wrong documents
  2. Use $inc for counters: Prevents race conditions
  3. Combine operators: Reduce round trips
  4. Use upsert wisely: Great for "save or create" patterns
  5. Use async for gameplay: Non-blocking updates

Next Steps