Crud Operations

Create Operations

Insert documents into MongoDB collections

InsertOne

Insert a single document into a collection.

local id = collection:InsertOne(document)

Parameters:

  • document (table): The document to insert

Returns:

  • string: The inserted document's ID

Basic Example

local players = db:Collection("players")

local id = players:InsertOne({
    steamid = "STEAM_0:1:12345",
    username = "Player1",
    level = 1,
    credits = 1000,
    created_at = os.time()
})

print("Inserted with ID:", id)

With Nested Data

local id = players:InsertOne({
    steamid = "STEAM_0:1:12345",
    username = "Player1",
    profile = {
        avatar = "https://example.com/avatar.jpg",
        bio = "Veteran player",
        country = "DE"
    },
    inventory = {
        { item = "weapon_pistol", amount = 1 },
        { item = "ammo_9mm", amount = 50 }
    },
    stats = {
        kills = 0,
        deaths = 0,
        playtime = 0
    }
})

Real-World Example

-- Save player when they join
hook.Add("PlayerInitialSpawn", "SaveNewPlayer", function(ply)
    local steamid = ply:SteamID()
    
    -- Check if player already exists
    local exists = players:FindOne({ steamid = steamid })
    
    if not exists then
        -- New player - create record
        local id = players:InsertOne({
            steamid = steamid,
            username = ply:Nick(),
            first_join = os.time(),
            last_seen = os.time(),
            playtime = 0,
            level = 1,
            credits = 1000,
            rank = "Member"
        })
        
        print("New player registered:", ply:Nick())
        ply:ChatPrint("Welcome! You've been granted 1000 credits.")
    end
end)

InsertMany

Insert multiple documents at once - much more efficient than calling InsertOne in a loop.

local ids = collection:InsertMany(documents)

Parameters:

  • documents (table): Array of documents to insert

Returns:

  • table: Array of inserted document IDs

Basic Example

local items = db:Collection("shop_items")

local ids = items:InsertMany({
    { name = "Health Kit", price = 50, category = "medical" },
    { name = "Armor Vest", price = 100, category = "armor" },
    { name = "Ammo Box", price = 25, category = "ammunition" },
    { name = "Energy Drink", price = 15, category = "consumable" }
})

print("Inserted", #ids, "items")
for i, id in ipairs(ids) do
    print(i .. ". ID:", id)
end

Initialize Game Data

-- Initialize server on first run
local function InitializeServerData()
    local jobsDB = db:Collection("jobs")
    
    -- Check if already initialized
    local count = jobsDB:Count({})
    if count > 0 then
        print("Jobs already initialized")
        return
    end
    
    -- Insert default jobs
    local ids = jobsDB:InsertMany({
        {
            id = "citizen",
            name = "Citizen",
            description = "Regular citizen",
            salary = 50,
            max_players = -1
        },
        {
            id = "police",
            name = "Police Officer",
            description = "Protect the city",
            salary = 100,
            max_players = 4,
            weapons = { "weapon_pistol", "weapon_stunstick" }
        },
        {
            id = "medic",
            name = "Medic",
            description = "Heal injured players",
            salary = 90,
            max_players = 2,
            weapons = { "weapon_medkit" }
        },
        {
            id = "mayor",
            name = "Mayor",
            description = "Lead the city",
            salary = 150,
            max_players = 1,
            vip_only = true
        }
    })
    
    print("Initialized", #ids, "jobs")
end

hook.Add("Initialize", "InitServerData", InitializeServerData)

Bulk Player Import

-- Import players from old system
local function ImportPlayers(oldData)
    local newPlayers = {}
    
    for steamid, data in pairs(oldData) do
        table.insert(newPlayers, {
            steamid = steamid,
            username = data.name,
            level = data.level or 1,
            credits = data.money or 0,
            playtime = data.playtime or 0,
            imported_at = os.time()
        })
    end
    
    if #newPlayers > 0 then
        local ids = players:InsertMany(newPlayers)
        print("Imported", #ids, "players from old system")
    end
end

Performance Comparison

Inserting 1000 documents:

  • Using InsertOne in a loop: ~2000ms
  • Using InsertMany: ~200ms
  • Result: 10x faster!

Bad (Slow)

-- DON'T DO THIS
for i = 1, 1000 do
    items:InsertOne({
        name = "Item " .. i,
        price = i * 10
    })
end
-- Takes ~2000ms

Good (Fast)

-- DO THIS INSTEAD
local items_to_insert = {}
for i = 1, 1000 do
    table.insert(items_to_insert, {
        name = "Item " .. i,
        price = i * 10
    })
end
items:InsertMany(items_to_insert)
-- Takes ~200ms

Auto-Generated Fields

MongoDB automatically adds an _id field to every document:

local id = players:InsertOne({
    username = "Player1"
})

-- id is a unique ObjectId string like "507f1f77bcf86cd799439011"

-- Retrieve the document
local doc = players:FindOne({ _id = id })
print(doc._id)  -- "507f1f77bcf86cd799439011"
print(doc.username)  -- "Player1"

Error Handling

Always handle potential errors:

local success, result = pcall(function()
    return players:InsertOne({
        steamid = "STEAM_0:1:12345",
        username = "Player1"
    })
end)

if success then
    print("Inserted successfully with ID:", result)
else
    print("Insert failed:", result)
    -- Log error, notify admin, etc.
end

Best Practices

  1. Use InsertMany for bulk inserts - it's 10x faster
  2. Validate data before inserting to maintain data integrity
  3. Use timestamps - always include created_at field
  4. Don't insert duplicates - check with FindOne first or use unique indexes
  5. Keep documents under 16MB - MongoDB's document size limit
  6. Use consistent field names - helps with queries and maintenance

Next Steps

Read Operations

Learn how to find and query documents

Update Operations

Modify existing documents