Query Builder#
Duxt ORM provides a fluent query builder with Rails-like syntax using Model<T>.
Basic Queries#
Setup#
// Create a query interface for any model
final users = Model<User>();
final posts = Model<Post>();
Retrieve All Records#
final allUsers = await users.all();
Find by ID#
final user = await users.find(1);
// Returns null if not found
final user = await users.findOrFail(1);
// Throws exception if not found
First Record#
final user = await users.first();
Count Records#
final count = await users.count();
Where Clauses#
Simple Where#
// Equality
users.where('is_active', 1)
// With operator
users.where('age', 18, '>=')
users.where('status', 'banned', '!=')
Multiple Conditions#
await users.query()
.where('is_active', 1)
.where('role', 'admin')
.get();
OR Conditions#
await users.query()
.where('role', 'admin')
.orWhere('role', 'moderator')
.get();
NULL Checks#
// Where column IS NULL
users.query().whereNull('deleted_at').get()
// Where column IS NOT NULL
users.query().whereNotNull('email_verified_at').get()
IN Clause#
// Where column IN (values)
users.query().whereIn('id', [1, 2, 3]).get()
// Where column NOT IN (values)
users.query().whereNotIn('status', ['banned', 'suspended']).get()
BETWEEN#
users.query().whereBetween('age', 18, 65).get()
LIKE#
users.query().whereLike('name', '%john%').get()
users.query().whereLike('email', '%@gmail.com').get()
Raw WHERE#
users.query()
.whereRaw('created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)')
.get()
Ordering#
final users = Model<User>();
// Ascending
users.query().orderBy('name').get()
// Descending
users.query().orderByDesc('created_at').get()
// Shortcuts for created_at
users.query().latest().get() // ORDER BY created_at DESC
users.query().oldest().get() // ORDER BY created_at ASC
Pagination#
final users = Model<User>();
await users.query()
.orderByDesc('created_at')
.skip(20) // OFFSET 20
.take(10) // LIMIT 10
.get();
Or use limit and offset:
await users.query()
.limit(10)
.offset(20)
.get();
Aggregates#
final users = Model<User>();
// Count with conditions
final activeCount = await users
.where('is_active', 1)
.count();
// Sum
final orders = Model<Order>();
final totalRevenue = await orders.query().sum('total');
// Average
final avgAge = await users.query().avg('age');
// Max and Min
final products = Model<Product>();
final maxPrice = await products.query().max('price');
final minPrice = await products.query().min('price');
Existence Checks#
final users = Model<User>();
// Check if any records exist
if (await users.where('email', email).exists()) {
print('Email already taken');
}
// Check if no records exist
if (await users.where('role', 'admin').doesntExist()) {
print('No admins yet');
}
Pluck (Single Column)#
final users = Model<User>();
// Get list of values from one column
final emails = await users.query().pluck('email');
// ['[email protected]', '[email protected]', ...]
final ids = await users
.where('is_active', 1)
.query()
.pluck('id');
// [1, 3, 5, 7, ...]
Select Specific Columns#
final users = Model<User>();
final result = await users.query()
.select(['id', 'name', 'email'])
.get();
Bulk Operations#
Update Multiple Records#
final users = Model<User>();
await users.query()
.where('last_login', DateTime(2023), '<')
.update({'is_active': 0});
Delete Multiple Records#
final users = Model<User>();
await users.query()
.where('is_active', 0)
.delete();
Increment / Decrement#
final posts = Model<Post>();
// Increment by 1
await posts.where('id', 1).query().increment('views');
// Increment by custom amount
final products = Model<Product>();
await products.where('id', 1).query().increment('stock', 10);
// Decrement
await products.where('id', 1).query().decrement('stock', 5);
Soft Delete Scopes#
By default, queries exclude soft-deleted records. Use these methods to change that behavior:
Include Soft-Deleted Records#
final posts = Model<Post>();
// Include trashed records in results
final all = await posts.withTrashed().get();
// Also works with other query methods
final count = await posts.withTrashed().count();
Only Soft-Deleted Records#
final posts = Model<Post>();
// Only return soft-deleted records
final trashed = await posts.onlyTrashed().get();
Restore and Force Delete via Query#
final posts = Model<Post>();
// Restore all trashed posts by a user
await posts.query()
.onlyTrashed()
.where('user_id', 1)
.restore();
// Permanently delete trashed records
await posts.query()
.onlyTrashed()
.where('user_id', 1)
.forceDelete();
Chaining Example#
final users = Model<User>();
final recentActiveAdmins = await users.query()
.select(['id', 'name', 'email', 'last_login'])
.where('is_active', 1)
.where('role', 'admin')
.whereNotNull('email_verified_at')
.whereBetween('created_at', startDate, endDate)
.orderByDesc('last_login')
.limit(10)
.get();
Complete Example#
import 'package:duxt_orm/duxt_orm.dart';
void main() async {
// Initialize
User.register();
Post.register();
await DuxtOrm.init(config);
// Use Model<T> for queries
final users = Model<User>();
final posts = Model<Post>();
// Find user
final user = await users.find(1);
// Get user's published posts
final userPosts = await posts
.where('user_id', user!.id)
.where('published', true)
.query()
.orderByDesc('created_at')
.get();
// Create new post
final newPost = await posts.create({
'title': 'Hello World',
'slug': 'hello-world',
'user_id': user.id,
'published': true,
});
print('Created post: ${newPost.title}');
}