CRUD Operations

Query Operators

MongoDB comparison, logical, and array operators

Query Operators

MongoDB query operators allow you to build powerful filters for your queries.

Comparison Operators

$eq - Equal

-- Implicit equality
collection:Find({ level = 10 })

-- Explicit $eq
collection:Find({ level = { ["$eq"] = 10 } })

$ne - Not Equal

-- Find players who are not banned
collection:Find({ banned = { ["$ne"] = true } })

-- Find non-warriors
collection:Find({ class = { ["$ne"] = "Warrior" } })

$gt - Greater Than

-- Players with level > 10
collection:Find({ level = { ["$gt"] = 10 } })

-- Recent logins (last 24 hours)
collection:Find({
    last_login = { ["$gt"] = os.time() - (24 * 60 * 60) }
})

$gte - Greater Than or Equal

-- Players with level >= 10
collection:Find({ level = { ["$gte"] = 10 } })

-- Credits at least 1000
collection:Find({ credits = { ["$gte"] = 1000 } })

$lt - Less Than

-- Players with level < 5
collection:Find({ level = { ["$lt"] = 5 } })

-- Old sessions (older than 1 hour)
collection:Find({
    created_at = { ["$lt"] = os.time() - 3600 }
})

$lte - Less Than or Equal

-- Players with level <= 5
collection:Find({ level = { ["$lte"] = 5 } })

Range Queries

Combine operators for ranges:

-- Level between 10 and 20 (inclusive)
collection:Find({
    level = { ["$gte"] = 10, ["$lte"] = 20 }
})

-- Credits between 1000 and 5000
collection:Find({
    credits = { ["$gte"] = 1000, ["$lt"] = 5000 }
})

Array Operators

$in - Match Any Value

-- Find specific classes
collection:Find({
    class = { ["$in"] = { "Warrior", "Mage", "Rogue" } }
})

-- Find specific players by SteamID
collection:Find({
    steamid = { ["$in"] = {
        "STEAM_0:1:11111",
        "STEAM_0:1:22222",
        "STEAM_0:1:33333"
    }}
})

$nin - Match None

-- Exclude specific classes
collection:Find({
    class = { ["$nin"] = { "Warrior", "Paladin" } }
})

-- Find players not in list
collection:Find({
    steamid = { ["$nin"] = bannedSteamIds }
})

$all - Match All Values

-- Players with all required achievements
collection:Find({
    achievements = { ["$all"] = { "first_kill", "level_10", "vip" } }
})

$size - Array Length

-- Players with exactly 5 items
collection:Find({
    inventory = { ["$size"] = 5 }
})

$elemMatch - Element Match

-- Players with high-damage weapons
collection:Find({
    inventory = {
        ["$elemMatch"] = {
            type = "weapon",
            damage = { ["$gte"] = 100 }
        }
    }
})

Logical Operators

$and - All Conditions

-- Implicit AND (multiple fields)
collection:Find({
    level = { ["$gte"] = 10 },
    vip = true,
    banned = false
})

-- Explicit $and
collection:Find({
    ["$and"] = {
        { level = { ["$gte"] = 10 } },
        { credits = { ["$gte"] = 1000 } }
    }
})

-- Useful when same field appears twice
collection:Find({
    ["$and"] = {
        { level = { ["$gte"] = 10 } },
        { level = { ["$lte"] = 20 } }
    }
})

$or - Any Condition

-- VIP or high level
collection:Find({
    ["$or"] = {
        { vip = true },
        { level = { ["$gte"] = 50 } }
    }
})

-- Multiple class options
collection:Find({
    ["$or"] = {
        { class = "Warrior" },
        { class = "Paladin" },
        { class = "Knight" }
    }
})

$nor - None of Conditions

-- Not banned AND not inactive
collection:Find({
    ["$nor"] = {
        { banned = true },
        { active = false }
    }
})

$not - Negate Condition

-- Level not greater than 10 (i.e., <= 10)
collection:Find({
    level = { ["$not"] = { ["$gt"] = 10 } }
})

Complex Combinations

-- Warriors with high level OR any VIP player
collection:Find({
    ["$or"] = {
        {
            class = "Warrior",
            level = { ["$gte"] = 20 }
        },
        { vip = true }
    }
})

-- (level >= 10 AND credits >= 1000) OR vip = true
collection:Find({
    ["$or"] = {
        {
            ["$and"] = {
                { level = { ["$gte"] = 10 } },
                { credits = { ["$gte"] = 1000 } }
            }
        },
        { vip = true }
    }
})

Element Operators

$exists - Field Exists

-- Players with inventory field
collection:Find({
    inventory = { ["$exists"] = true }
})

-- Players without email set
collection:Find({
    email = { ["$exists"] = false }
})

$type - Field Type

-- Documents where level is a number
collection:Find({
    level = { ["$type"] = "number" }
})

-- Type codes: "string", "number", "object", "array", "bool", "null"

Evaluation Operators

$regex - Regular Expression

-- Names starting with "A"
collection:Find({
    username = { ["$regex"] = "^A" }
})

-- Names containing "player" (case insensitive)
collection:Find({
    username = { ["$regex"] = "player", ["$options"] = "i" }
})

$mod - Modulo

-- Players with even levels
collection:Find({
    level = { ["$mod"] = { 2, 0 } }  -- level % 2 == 0
})

Practical Examples

Active VIP Players

local sevenDaysAgo = os.time() - (7 * 24 * 60 * 60)

local activeVips = collection:Find({
    vip = true,
    last_login = { ["$gte"] = sevenDaysAgo },
    banned = { ["$ne"] = true }
})

Search System

function SearchPlayers(criteria)
    local filter = {}

    -- Level range
    if criteria.minLevel or criteria.maxLevel then
        filter.level = {}
        if criteria.minLevel then
            filter.level["$gte"] = criteria.minLevel
        end
        if criteria.maxLevel then
            filter.level["$lte"] = criteria.maxLevel
        end
    end

    -- Class filter
    if criteria.classes and #criteria.classes > 0 then
        filter.class = { ["$in"] = criteria.classes }
    end

    -- VIP only
    if criteria.vipOnly then
        filter.vip = true
    end

    -- Not banned
    filter.banned = { ["$ne"] = true }

    return collection:Find(filter, criteria.limit or 100)
end

-- Usage
local results = SearchPlayers({
    minLevel = 10,
    maxLevel = 50,
    classes = { "Warrior", "Mage" },
    vipOnly = true,
    limit = 20
})

Matchmaking Query

function FindMatchingPlayers(targetLevel, range)
    return collection:Find({
        level = {
            ["$gte"] = targetLevel - range,
            ["$lte"] = targetLevel + range
        },
        in_queue = true,
        banned = { ["$ne"] = true }
    }, 10)  -- Max 10 players
end

Leaderboard Query

function GetClassLeaderboard(className)
    return collection:Find({
        class = className,
        banned = { ["$ne"] = true },
        ["$or"] = {
            { hidden_profile = { ["$exists"] = false } },
            { hidden_profile = false }
        }
    })
end

Update Operator Reference

For completeness, here are update operators:

OperatorDescription
$setSet field value
$unsetRemove field
$incIncrement by value
$mulMultiply by value
$minUpdate if less than
$maxUpdate if greater than
$pushAdd to array
$pullRemove from array
$addToSetAdd unique to array
$popRemove first/last from array

Best Practices

  1. Use indexes: Index fields used in filters
  2. Be specific: More specific filters = faster queries
  3. Avoid $regex on large collections: Unless indexed
  4. Use $in over multiple $or: More efficient
  5. Test your queries: Verify expected results

Next Steps