CRUD Operations
Create, Read, Update, and Delete operations on models through database.Get(). Nimbus extends GORM with type-safe generic helpers for common patterns.
Create
// Single record
post := Post{Title: "Hello", Content: "World", Status: "draft"}
result := database.Get().Create(&post)
// post.ID, post.CreatedAt, post.UpdatedAt are automatically set
// Batch create
posts := []Post{
{Title: "First", Status: "draft"},
{Title: "Second", Status: "published"},
}
database.Get().Create(&posts)
Read
db := database.Get()
// By primary key
var post Post
db.First(&post, 1)
// By condition
db.First(&post, "slug = ?", "hello-world")
// Find or error (returns gorm.ErrRecordNotFound)
err := db.First(&post, "id = ?", id).Error
// All records
var posts []Post
db.Find(&posts)
// With conditions
db.Where("status = ?", "published").Find(&posts)
// Count
var count int64
db.Model(&Post{}).Where("status = ?", "published").Count(&count)
Update
// Update single field
db.Model(&post).Update("title", "New Title")
// Update multiple fields
db.Model(&post).Updates(map[string]any{
"title": "New Title",
"status": "published",
})
// Update with struct (only non-zero fields)
db.Model(&post).Updates(Post{Title: "New", Status: "published"})
// Save full model (insert or update)
post.Title = "Updated Title"
post.Content = "New content"
db.Save(&post)
Delete
// Soft delete (when model has gorm.DeletedAt field)
db.Delete(&post)
// Hard delete (bypass soft delete)
db.Unscoped().Delete(&post)
// Delete by condition
db.Where("status = ?", "draft").Delete(&Post{})
FirstOrCreate / UpdateOrCreate
// Find by attributes, or create if not found
db.Where(Post{Slug: "unique-post"}).FirstOrCreate(&post)
// With additional attributes on create
db.Where(User{Email: "a@b.com"}).
Attrs(User{Name: "Default Name"}).
FirstOrCreate(&user)
// Generic helper (type-safe)
user, err := database.FirstOrCreate[User](db, User{Email: "a@b.com"})
// UpdateOrCreate — upsert (find or create + update)
user, err := database.UpdateOrCreate[User](db,
User{Email: "a@b.com"}, // search attributes
map[string]any{"name": "Updated"}, // attributes to update
)
Generic Helpers
| Function | Description |
|---|---|
FirstOrCreate[T](db, attrs) | Find or create, returns typed result |
UpdateOrCreate[T](db, where, update) | Upsert with typed result |
Exists(query) | Returns true if any record matches |
Pluck[T](query, col) | Extract column values as typed slice |
CountBy(query, col) | Group-count into map[string]int64 |
Chunk[T](db, size, fn) | Process records in batches |
CachedFind[T](db, id, ttl) | Find with in-memory cache |
// Check if a slug exists
if database.Exists(db.Model(&Post{}).Where("slug = ?", slug)) {
return c.JSON(409, map[string]string{"error": "slug taken"})
}
// Get all emails
emails, _ := database.Pluck[string](db.Model(&User{}), "email")
// Count posts by status
stats := database.CountBy(db.Model(&Post{}), "status")
// map[string]int64{"draft": 3, "published": 10, "archived": 2}
// Process 50,000 users in batches of 100
database.Chunk[User](db, 100, func(users []User) error {
for _, u := range users {
sendNewsletter(u)
}
return nil
})
Transactions
err := database.Transaction(func(tx *gorm.DB) error {
if err := tx.Create(&order).Error; err != nil {
return err // auto-rollback
}
if err := tx.Create(&payment).Error; err != nil {
return err // auto-rollback
}
return nil // auto-commit
})