Models
Models provide an abstraction layer for working with ArangoDB, including CRUD operations and validations.
Multi-model graph database
Built-in data validation
Powerful query language
architecture Defining Models
Models extend arango_model and define a collection name.
Customer Model
app/models/customer.lua
local model = require("arango_model")
local Customer = setmetatable({}, { __index = model })
Customer.__index = Customer
Customer.COLLECTION = "customers"
function Customer.new(data)
local self = setmetatable(model.new(data), Customer)
return self
end
return Customer
info Key elements:
COLLECTION — defines the ArangoDB collection name
new(data) — constructor that initializes the model
arango_model
sync_alt CRUD Operations
Models provide methods for Create, Read, Update, and Delete operations.
local Customer = require("models/customer")
-- Create
local customer = Customer.new():create({
name = "John Doe",
email = "john@example.com"
})
-- Read (via AQL or direct document access)
local doc = Adb.primary:GetDocument(customer._id)
-- Update
Adb.primary:UpdateDocument(customer._id, {
name = "Jane Doe"
})
-- Delete
Adb.primary:DeleteDocument(customer._id)
verified Validations
Define validations in the model constructor to validate data before saving.
Model with Validations
Define validation rules in new()
function Customer.new(data)
local self = setmetatable(model.new(data), Customer)
self.validations = {
name = { presence = { message = "Name is required" } },
email = {
presence = true,
format = [[^[%w.]+@[%w.]+%.[%w]+$]]
},
age = { numericality = { only_integer = true } }
}
return self
end
-- Usage
local customer = Customer.new():create({ name = "John" })
if #customer.errors > 0 then
-- Handle validation errors
for _, err in ipairs(customer.errors) do
print(err.field .. ": " .. err.message)
end
end
Available Validators
name = { presence = { message = "Name is required" } }
-- or simply
name = { presence = true }
price = { numericality = true }
age = { numericality = { only_integer = true, message = "Must be an integer" } }
code = { length = 10 } -- exactly 10 characters
code = { length = { eq = 10 } } -- exactly 10 characters
name = { length = { minimum = 2 } } -- at least 2 characters
name = { length = { maximum = 100 } } -- at most 100 characters
name = { length = { between = { 2, 100 } } } -- between 2 and 100
phone = { format = [[^\d+$]] } -- only digits
color = { inclusion = { values = { "red", "green", "blue" } } }
status = { exclusion = { values = { "banned", "suspended" } } }
password_confirm = { comparaison = "password" } -- equal
end_date = { comparaison = { gt = "start_date" } } -- greater than
end_date = { comparaison = { gte = "start_date" } } -- greater or equal
value = { comparaison = { lt = "max_value" } } -- less than
value = { comparaison = { lte = "max_value" } } -- less or equal
username = { comparaison = { other_than = "old_username" } } -- not equal
terms = { acceptance = true }
terminal Direct ArangoDB Access
Use Adb.primary for direct database operations.
| Method | Description |
|---|---|
Aql(query) |
Execute an AQL query |
CreateDocument(collection, data) |
Create a new document |
GetDocument(id) |
Retrieve a document by _id |
UpdateDocument(id, data) |
Update an existing document |
DeleteDocument(id) |
Delete a document |
CreateCollection(name) |
Create a new collection |
DeleteCollection(name) |
Delete a collection |
CreateIndex(collection, options) |
Create an index on a collection |
BeginTransaction(options) |
Start a stream transaction |
code AQL Queries
Execute ArangoDB Query Language (AQL) for complex queries.
-- Simple query
local result = Adb.primary:Aql("RETURN UUID()")
local uuid = result.result[1]
-- Query with bind parameters
local customers = Adb.primary:Aql([[
FOR c IN customers
FILTER c.status == @status
SORT c.created_at DESC
LIMIT @limit
RETURN c
]], { status = "active", limit = 10 })
-- Handle results
for _, customer in ipairs(customers.result) do
print(customer.name)
end
-- Error handling
if customers.error then
print("Error: " .. customers.errorMessage)
end
sync Transactions
Use transactions for atomic operations across multiple documents.
Stream Transactions
-- Begin transaction
local tx = Adb.primary:BeginTransaction({
collections = {
write = { "orders", "inventory" }
}
})
-- Perform operations...
-- Commit or abort
Adb.primary:CommitTransaction(tx.result.id)
-- or
Adb.primary:AbortTransaction(tx.result.id)
JavaScript Transactions
local result = Adb.primary:Transaction({
collections = {
read = "customers"
},
action = [[
function() {
// JavaScript code here
return db.customers.count();
}
]]
})
Pro Tips
Indexes: Create indexes on frequently queried fields to improve performance.
Validations: Always validate user input before saving to prevent bad data.
AQL: Use bind parameters (@param) instead of string concatenation to prevent injection attacks.