Beta documentation. This is an early preview — content is still in active development. Feedback helps shape the final release. Share your thoughts or join the discussion.

api.dataset

`api.dataset` is Wapka's built-in NoSQL document store. Think MongoDB or Firebase — without any setup. Collections auto-create on first insert. Every documen...

On this page

Your own database

api.dataset is Wapka's built-in NoSQL document store. Think MongoDB or Firebase — without any setup. Collections auto-create on first insert. Every document is a JSON object.

Function reference

Function Returns Description
api.dataset.collections() string[] List all collection names
api.dataset.get(id) table or nil Get a document by ID
api.dataset.find(collection, filter?) { items, total } Query documents
api.dataset.create(collection, data) table Create a document
api.dataset.update(id, data, replace?) table Update. replace=true for full replace
api.dataset.delete(id, permanent?) boolean Delete. permanent=true for hard delete
api.dataset.restore(id) table Restore soft-deleted document
api.dataset.purge_collection(name) number Delete all documents in a collection

Your first document

-- Creates "products" collection automatically
api.dataset.create("products", {
    name = "Widget",
    price = 9.99,
    stock = 100,
    tags = { "new", "sale" }
})

No schema definition. No table creation. Just insert.

Finding documents

-- All products
local result = api.dataset.find("products")

-- Filtered
local result = api.dataset.find("products", {
    filter = { status = "active" }
})

-- With pagination and sort
local result = api.dataset.find("products", {
    filter = { status = "active" },
    order = "price_asc",       -- cheapest first
    page = 1,
    limit = 20
})

for _, doc in ipairs(result.items) do
    print(doc.data.name, doc.data.price)
end

All query operators

Filters use operators for comparisons. No $ prefix — just the operator name.

Operator Meaning Example
eq Equal (default, can omit) { status = "active" }
neq Not equal { status = { neq = "deleted" } }
gt Greater than { price = { gt = 100 } }
gte Greater or equal { stock = { gte = 1 } }
lt Less than { age = { lt = 18 } }
lte Less or equal { score = { lte = 100 } }
in In array { role = { in = { "admin", "editor" } } }
nin Not in array { status = { nin = { "banned" } } }
regex Pattern match { name = { regex = "^A" } }
like SQL LIKE (%) { title = { like = "%lua%" } }
contains JSON_CONTAINS { tags = { contains = "sale" } }
null Field is null { deleted_at = { null = true } }
exists Field exists { email = { exists = true } }

Real-world query examples

Products: active, in stock, priced $10-$100

local result = api.dataset.find("products", {
    filter = {
        status = "active",
        stock = { gt = 0 },
        price = { gte = 10, lte = 100 }
    },
    order = "price_asc",
    limit = 20
})

Users: search by name pattern

local result = api.dataset.find("users", {
    filter = {
        name = { like = "%" .. search_term .. "%" }
    }
})

Posts: newest featured content

local result = api.dataset.find("posts", {
    filter = {
        status = "published",
        featured = true
    },
    order = "id_desc",
    limit = 10
})

Products with multiple tags

local result = api.dataset.find("products", {
    filter = {
        tags = { contains = "sale" },
        category = { in = { "electronics", "computers" } }
    }
})

Update: merge vs replace

-- Merge (default): only changes specified fields
api.dataset.update(500, {
    data = { price = 14.99, stock = 50 }
})
-- Other fields (name, tags) stay unchanged

-- Full replace: entire document is replaced
api.dataset.update(500, {
    data = { name = "New Widget", price = 19.99 }
}, true)
-- All other fields are gone

Soft vs hard delete

-- Soft delete (can be restored)
api.dataset.delete(500)

-- Hard delete (permanent)
api.dataset.delete(500, true)

-- Restore
api.dataset.restore(500)

Purge a collection

-- Delete everything in a collection
api.dataset.purge_collection("temp_logs")

Warning: purge_collection is instant and permanent. There is no undo.

Building a product catalog

app:get("/products", function(ctx)
    local page = tonumber(req.query.page) or 1
    local search = req.query.q
    local category = req.query.cat

    local filter = { status = "active" }
    if search then
        filter.name = { like = "%" .. search .. "%" }
    end
    if category then
        filter.category = category
    end

    local result = api.dataset.find("products", {
        filter = filter,
        order = "id_desc",
        page = page,
        limit = 12
    })

    return ctx:render("products", {
        products = result.items,
        total = result.total,
        page = page
    })
end)

app:get("/products/:id", function(ctx)
    local result = api.dataset.find("products", {
        filter = { id = { eq = tonumber(ctx.params.id) } },
        limit = 1
    })
    if result.total == 0 then
        return ctx:error("Product not found", 404)
    end
    return ctx:render("product", { product = result.items[1] })
end)

Or use the OR condition

-- Find posts that are either featured OR have high views
local result = api.dataset.find("posts", {
    filter = {
        or = {
            { featured = true },
            { views = { gte = 1000 } }
        },
        status = "published"  -- AND with the OR group
    }
})

Note: api.dataset is the Lua wrapper around the REST API dataset endpoints. For even more advanced querying, see the Dataset Advanced Querying guide.

Next: Explore the Standard Library — 108 utility functions for HTTP, hashing, encoding, and strings.

Previous api.pages & api.codes