English | 中文文档
Eloquent is a code-generation based database ORM framework for Go, inspired by the Eloquent ORM in the PHP framework Laravel. Supports MySQL and PostgreSQL.
- Core Concepts
- Quick Start
- Installation
- Model Definition & Code Generation
- Database Dialect (MySQL / PostgreSQL)
- Database Connection
- CRUD Operations
- Query Builder
- Model Relationships
- Soft Deletes
- Scopes
- Database Migrations
- Transactions
- Event System
- Direct Database Operations
- Example Projects
Understanding these core concepts will help you get started with Eloquent quickly:
Eloquent does not use runtime reflection to map database tables. Instead, it works through a YAML model definition -> CLI tool generates Go code workflow:
- Write a YAML file describing your database table structure
- Run the
eloquent gencommand to generate the corresponding Go code (*.orm.gofiles) - The generated code contains type-safe model structs and complete CRUD methods
For each model (e.g., User), Eloquent generates two structs:
UserN(Nullable version): All fields usenull.Int,null.String, etc. (fromgopkg.in/guregu/null.v3), correctly handlingNULLvalues from the database. This is the primary struct used for database interaction.User(Plain version): All fields use Go primitive types (int64,string, etc.). When a database field isNULL, it returns the zero value. Suitable for use in business logic.
They can be converted to each other:
// UserN -> User (Nullable -> Plain)
user := userN.ToUser()
// User -> UserN (Plain -> Nullable)
userN := user.ToUserN()All query conditions are built through query.Builder() chained calls, rather than writing raw SQL. The query builder supports Where, WhereIn, OrderBy, Limit, and other common operations.
All database operations require a context.Context parameter, following Go best practices for timeout control and cancellation.
Here is a complete example showing the full workflow from model definition to database operations.
go install github.com/mylxsw/eloquent/cmd/orm@latestThis gives you an orm CLI tool (you can also build the project yourself to get an eloquent binary).
You can write YAML manually or use the CLI to generate a basic template:
eloquent create-model --table users --package models --soft-delete --output ./models/Then edit the generated users.yaml file to add the fields you need:
package: models
models:
- name: User
definition:
table_name: users
soft_delete: true
fields:
- name: id
type: int64
tag: 'json:"id"'
- name: name
type: string
tag: 'json:"name"'
- name: email
type: string
tag: 'json:"email"'
- name: age
type: int64
tag: 'json:"age"'eloquent gen --source './models/*.yaml'This generates a users.orm.go file in the same directory, containing UserN, User, UserModel, and all related code.
Note: Generated
*.orm.gofiles should not be manually modified, as they are regenerated each time thegencommand is run.
go get github.com/mylxsw/eloquent
go get gopkg.in/guregu/null.v3
# For MySQL
go get github.com/go-sql-driver/mysql
# For PostgreSQL (use one of the following)
go get github.com/lib/pq
# or: go get github.com/jackc/pgx/v5package main
import (
"context"
"database/sql"
"fmt"
"yourproject/models"
_ "github.com/go-sql-driver/mysql"
"gopkg.in/guregu/null.v3"
)
func main() {
db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/mydb?parseTime=true")
if err != nil {
panic(err)
}
defer db.Close()
ctx := context.TODO()
userModel := models.NewUserModel(db)
// Create a user
id, err := userModel.Save(ctx, models.UserN{
Name: null.StringFrom("Tom"),
Email: null.StringFrom("[email protected]"),
Age: null.IntFrom(25),
})
fmt.Printf("New user ID: %d\n", id)
// Query a user
user, err := userModel.Find(ctx, id)
fmt.Printf("Name: %s, Email: %s\n", user.Name.String, user.Email.String)
// Convert to Plain struct
u := user.ToUser()
fmt.Printf("Name: %s, Age: %d\n", u.Name, u.Age)
}Add the Eloquent dependency to your project:
go get github.com/mylxsw/eloquentBuild the CLI tool (for code generation):
# Option 1: Direct install
go install github.com/mylxsw/eloquent/cmd/orm@latest
# Option 2: Clone and build
git clone https://github.com/mylxsw/eloquent.git
cd eloquent
make build
# Binary is generated at ./bin/eloquentModel definitions use YAML format. Here is a complete field reference:
package: models # Go package name for generated code
imports: # Additional packages to import (when fields use external types)
- github.com/mylxsw/eloquent
meta:
table_prefix: wz_ # Table prefix, automatically prepended to table names
models:
- name: User # Model name (generated struct name)
definition:
table_name: users # Database table name (defaults to snake_case of model name)
without_create_time: false # Set to true to skip adding created_at field
without_update_time: false # Set to true to skip adding updated_at field
soft_delete: false # Set to true to enable soft deletes (adds deleted_at field)
fields:
- name: id # Field name (snake_case)
type: int64 # Go type
tag: 'json:"id"' # Struct tag
- name: name
type: string
tag: 'json:"name"'You can use all Go primitive types, as well as external types imported via imports:
int,int64,int32, and other integer typesfloat32,float64stringtime.Time- Custom types (declare the package path in
imports)
When
typeis not specified, it defaults tostring.
Unless explicitly disabled, Eloquent automatically adds the following fields to each model:
| Field | Type | Description | Disable With |
|---|---|---|---|
created_at |
time.Time |
Creation time, auto-set on insert | without_create_time: true |
updated_at |
time.Time |
Update time, auto-set on update | without_update_time: true |
deleted_at |
time.Time |
Deletion time, auto-set on soft delete | Only added when soft_delete: true |
# Generate model code
eloquent gen --source './models/*.yaml'
# Create a model definition file template
eloquent create-model \
--table users \
--package models \
--output ./models/ \
--table-prefix wz_ \
--soft-delete \
--no-created_at \
--no-updated_at \
--import "github.com/mylxsw/eloquent"For a User model, the generated code includes:
| Content | Description |
|---|---|
UserN struct |
Nullable version, fields use null.Int, null.String, etc. |
User struct |
Plain version, fields use Go primitive types |
UserModel |
Model operation object, provides all CRUD methods |
NewUserModel(db) |
Factory function to create a model instance |
FieldUser* constants |
Constant definitions for each field name, e.g., FieldUserName = "name" |
UserFields() |
Returns a slice of all field names |
UserTable() |
Returns the table name |
| Relationship methods | Generated if relations are defined |
Eloquent supports both MySQL and PostgreSQL through a dialect system. By default, MySQL dialect is used. To switch to PostgreSQL, set the dialects at application startup:
import (
"github.com/mylxsw/eloquent/query"
"github.com/mylxsw/eloquent/migrate"
)
// Switch to PostgreSQL mode (call once at startup, before any database operations)
query.SetDialect(query.PostgreSQLDialect{})
migrate.SetMigrateDialect(migrate.PostgreSQLMigrateDialect{})The dialect system automatically handles the differences between MySQL and PostgreSQL:
| Feature | MySQL | PostgreSQL |
|---|---|---|
| Identifier quoting | `name` |
"name" |
| Parameter placeholders | ? |
$1, $2, ... |
| Auto-increment primary key | AUTO_INCREMENT PRIMARY KEY |
SERIAL PRIMARY KEY |
| Insert returning ID | LastInsertId() |
INSERT ... RETURNING id |
| Engine / Charset / Collation | Supported | Ignored (not applicable) |
TINYINT(1) |
TINYINT(1) |
BOOLEAN |
BLOB |
BLOB |
BYTEA |
LONGTEXT / MEDIUMTEXT |
As-is | TEXT |
JSON |
JSON |
JSONB |
DATETIME |
DATETIME |
TIMESTAMP |
UNSIGNED |
Supported | Ignored (not applicable) |
| Index creation | ALTER TABLE ... ADD INDEX |
CREATE INDEX ... ON |
| Drop index | ALTER TABLE ... DROP INDEX |
DROP INDEX |
| Drop foreign key | DROP FOREIGN KEY |
DROP CONSTRAINT |
Note: When using raw SQL in migrations (
Schema.Raw()), you are responsible for writing database-specific SQL yourself.
Eloquent uses Go's standard database/sql library to manage database connections.
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
db, err := sql.Open("mysql", "root:password@tcp(127.0.0.1:3306)/mydb?parseTime=true")
if err != nil {
panic(err)
}
defer db.Close()Important: You must include
parseTime=truein the connection string, otherwise time fields cannot be parsed correctly.
import (
"database/sql"
_ "github.com/lib/pq"
"github.com/mylxsw/eloquent/query"
"github.com/mylxsw/eloquent/migrate"
)
// Set dialect before opening the connection
query.SetDialect(query.PostgreSQLDialect{})
migrate.SetMigrateDialect(migrate.PostgreSQLMigrateDialect{})
db, err := sql.Open("postgres", "host=127.0.0.1 port=5432 user=postgres password=secret dbname=mydb sslmode=disable")
if err != nil {
panic(err)
}
defer db.Close()Tip: You can also use
pgxas the PostgreSQL driver by importinggithub.com/jackc/pgx/v5/stdlibinstead ofgithub.com/lib/pq.
All operations require creating a model instance first:
userModel := models.NewUserModel(db)
ctx := context.TODO()// Method 1: Using Save with a Nullable struct
id, err := userModel.Save(ctx, models.UserN{
Name: null.StringFrom("Tom"),
Email: null.StringFrom("[email protected]"),
})
// Method 2: Using Create with KV pairs
id, err := userModel.Create(ctx, query.KV{
models.FieldUserName: "Tom",
models.FieldUserEmail: "[email protected]",
})
// Method 3: Converting from a Plain struct
user := models.User{Name: "Tom", Email: "[email protected]"}
id, err := userModel.Save(ctx, user.ToUserN())// Find by ID
user, err := userModel.Find(ctx, 1)
// Find the first matching record
user, err := userModel.First(ctx, query.Builder().Where("name", "Tom"))
// Get all records
users, err := userModel.Get(ctx)
// Get with conditions
users, err := userModel.Get(ctx, query.Builder().
Where("age", ">", 18).
OrderBy("created_at", "DESC").
Limit(10),
)
// Select specific fields
users, err := userModel.Get(ctx, query.Builder().Select("id", "name"))
// Pagination
users, meta, err := userModel.Paginate(ctx, 1, 15) // Page 1, 15 per page
// meta.Total - total record count
// meta.LastPage - last page number
// meta.Page - current page
// meta.PerPage - records per page
// Count
count, err := userModel.Count(ctx)
// Check existence
exists, err := userModel.Exists(ctx, query.Builder().Where("email", "[email protected]"))user, _ := userModel.Find(ctx, 1)
// Method 1: Read directly from Nullable struct
name := user.Name.String // Direct read, empty string if NULL
id := user.Id.Int64 // Direct int64 read
valid := user.Name.Valid // Check if field is NULL
// Method 2: Convert to Plain struct
u := user.ToUser()
fmt.Println(u.Name) // string type
fmt.Println(u.Age) // int64 type
// Method 3: Convert to a custom struct (matched by field name)
type UserView struct {
Name string
Email string
}
var view UserView
err := user.As(&view)// Method 1: Update specific fields via model method
affected, err := userModel.UpdateFields(ctx,
query.KV{models.FieldUserName: "Jerry"},
query.Builder().Where("id", 1),
)
// Method 2: Save via model instance (updates all modified fields)
user, _ := userModel.Find(ctx, 1)
user.Name = null.StringFrom("Jerry")
err := user.Save(ctx) // Requires SetModel or obtained via Find// Delete by ID (soft delete if enabled)
affected, err := userModel.DeleteById(ctx, 1)
// Delete with conditions
affected, err := userModel.Delete(ctx, query.Builder().Where("age", "<", 18))
// Force delete (physical delete even if soft delete is enabled)
affected, err := userModel.ForceDeleteById(ctx, 1)The query builder is the core tool for constructing SQL query conditions in Eloquent. All conditions start with query.Builder() and support chaining.
// Equals (default operator)
query.Builder().Where("name", "Tom")
// Specify operator
query.Builder().Where("age", ">", 18)
query.Builder().Where("name", "LIKE", "%Tom%")
// Available operator constants
query.EQ // =
query.NEQ // !=
query.GT // >
query.GTE // >=
query.LT // <
query.LTE // <=
query.LIKE // LIKEquery.Builder().Where("name", "Tom").OrWhere("name", "Jerry")
// WHERE name = 'Tom' OR name = 'Jerry'query.Builder().WhereIn("id", 1, 2, 3)
query.Builder().WhereNotIn("status", 0, -1)
// When using slices, convert first
ids := []int{1, 2, 3}
query.Builder().WhereIn("id", query.ToAnys(ids)...)query.Builder().WhereNull("deleted_at")
query.Builder().WhereNotNull("email")query.Builder().WhereBetween("age", 18, 30)
query.Builder().WhereNotBetween("age", 0, 17)// WHERE (name = 'Tom' AND age > 18) OR (name = 'Jerry')
query.Builder().
WhereGroup(func(builder query.Condition) {
builder.Where("name", "Tom").Where("age", ">", 18)
}).
OrWhereGroup(func(builder query.Condition) {
builder.Where("name", "Jerry")
})Dynamically add query conditions based on runtime values:
keyword := "Tom"
query.Builder().When(
func() bool { return keyword != "" },
func(builder query.Condition) {
builder.Where("name", "LIKE", "%"+keyword+"%")
},
)query.Builder().WhereRaw("YEAR(created_at) = ?", 2024)// WHERE id IN (SELECT user_id FROM orders WHERE amount > 100)
query.Builder().WhereIn("id",
query.Builder().Table("orders").Select("user_id").Where("amount", ">", 100),
)
// WHERE EXISTS (SELECT 1 FROM orders WHERE orders.user_id = users.id)
query.Builder().WhereExist(
query.Builder().Table("orders").Select(query.Raw("1")).WhereColumn("orders.user_id", "=", "users.id"),
)query.Builder().
OrderBy("created_at", "DESC").
OrderBy("id", "ASC").
Limit(10).
Offset(20).
GroupBy("status").
Having(func(builder query.Condition) {
builder.WhereRaw("COUNT(*) > ?", 5)
})query.Builder().
Table("users AS u").
Select("u.name", "r.name AS role_name").
LeftJoin("roles AS r", func(builder query.Condition) {
builder.WhereColumn("u.role_id", "=", "r.id")
})Supported JOIN types: LeftJoin, RightJoin, InnerJoin, CrossJoin
query.Builder().Table("table1").Select("name").
Union(query.Builder().Table("table2").Select("name"), false) // false=UNION ALL, true=UNION DISTINCTquery.Builder().Select("id", "name", query.Raw("DATE(created_at) AS create_date"))Eloquent supports relationship types defined via relations in the YAML file.
| Relationship | rel Value in YAML |
Description | Example |
|---|---|---|---|
| One-to-One | hasOne |
Current model owns one child model | User has one profile |
| Belongs To | belongsTo |
Current model belongs to another model | User belongs to a role |
| Many-to-Many | belongsToMany |
Related through a pivot table | User belongs to many organizations |
models:
- name: User
relations:
# Belongs To: User belongs to a role
- model: role
rel: belongsTo
foreign_key: role_id # Foreign key in current table
owner_key: id # Primary key in related table
# Has One: User has one extension record
- model: userExt
rel: hasOne
# Default foreign key is user_id (current_model_name_id)
# Many-to-Many: User belongs to many organizations
- model: organization
rel: belongsToMany
# Default pivot table is user_organization_ref
definition:
fields:
- name: id
type: int64
- name: role_id
type: int64user, _ := userModel.Find(ctx, 1)
// belongsTo - Query the user's role
role, err := user.Role().First(ctx)
// belongsTo - Create a related object and auto-bind the foreign key
roleId, err := user.Role().Create(ctx, models.RoleN{
Name: null.StringFrom("admin"),
})
// belongsTo - Associate / Dissociate
err = user.Role().Associate(ctx, role) // Bind
err = user.Role().Dissociate(ctx) // Unbind
// hasOne - Query user extension
ext, err := user.UserExt().First(ctx)
exists, err := user.UserExt().Exists(ctx)
// belongsToMany - Query all organizations for the user
orgs, err := user.Organizations().Get(ctx)
count, err := user.Organizations().Count(ctx)
// belongsToMany - Attach / Detach
err = user.Organizations().Attach(ctx, org) // Insert into pivot table
err = user.Organizations().Detach(ctx, org) // Remove from pivot table
err = user.Organizations().DetachAll(ctx) // Remove all associations
orgId, err := user.Organizations().Create(ctx, models.OrganizationN{
Name: null.StringFrom("Engineering"),
})When soft deletes are enabled, calling Delete does not physically remove data -- it sets the deleted_at field instead. Queries automatically filter out soft-deleted records.
Set soft_delete: true in the YAML:
models:
- name: User
definition:
soft_delete: true
fields:
- name: id
type: int64// Soft delete (sets deleted_at)
userModel.DeleteById(ctx, 1)
// Normal query (automatically excludes deleted records)
users, _ := userModel.Get(ctx)
// Query including deleted records
users, _ := userModel.WithTrashed().Get(ctx)
// Force delete (physically removes from database)
userModel.ForceDeleteById(ctx, 1)Scopes encapsulate commonly used query conditions into reusable functions.
Global scopes are automatically applied to all queries on a model. Soft delete is implemented via a global scope.
// Register a global scope (typically in an init function)
models.AddGlobalScopeForUser("active_only", func(builder query.Condition) {
builder.Where("status", 1)
})
// Automatically applied during queries
users, _ := userModel.Get(ctx) // Automatically adds WHERE status = 1
// Temporarily disable a global scope
users, _ := userModel.WithoutGlobalScopes("active_only").Get(ctx)Local scopes are not automatically applied; they must be explicitly enabled.
// Register a local scope
models.AddLocalScopeForUser("recent", func(builder query.Condition) {
builder.WhereRaw("created_at > DATE_SUB(NOW(), INTERVAL 7 DAY)")
})
// Explicitly enable
users, _ := userModel.WithLocalScopes("recent").Get(ctx)Eloquent provides Laravel-like database migration functionality, managing table schema changes through Go code.
import "github.com/mylxsw/eloquent/migrate"
m := migrate.NewManager(db).Init(context.TODO())
// Create a new table
m.Schema("20240101_001").Create("users", func(builder *migrate.Builder) {
builder.Increments("id")
builder.String("name", 100).Comment("Username")
builder.String("email", 255).Unique().Comment("Email")
builder.String("password", 255)
builder.Timestamps(0)
})
// Modify an existing table (add columns)
m.Schema("20240101_002").Table("users", func(builder *migrate.Builder) {
builder.TinyInteger("status", false, true).
Default(migrate.StringExpr("1")).
Comment("Status: 0-disabled 1-enabled")
builder.SoftDeletes("deleted_at", 0)
})
// Run migrations
if err := m.Run(context.TODO()); err != nil {
panic(err)
}Each
Schemaversion string is a unique identifier. Already-executed migrations will not be re-run. Eloquent automatically creates amigrationstable to track migration history.
| Method | MySQL Type | PostgreSQL Type |
|---|---|---|
Increments(name) |
INT UNSIGNED AUTO_INCREMENT | SERIAL |
BigIncrements(name) |
BIGINT UNSIGNED AUTO_INCREMENT | BIGSERIAL |
Integer(name, autoIncrement, unsigned) |
INT | INTEGER |
BigInteger(name, autoIncrement, unsigned) |
BIGINT | BIGINT |
TinyInteger(name, autoIncrement, unsigned) |
TINYINT | SMALLINT |
SmallInteger(name, autoIncrement, unsigned) |
SMALLINT | SMALLINT |
MediumInteger(name, autoIncrement, unsigned) |
MEDIUMINT | INTEGER |
Float(name, total, scale) |
DOUBLE | DOUBLE PRECISION |
Double(name, total, scale) |
DOUBLE | DOUBLE PRECISION |
Decimal(name, total, scale) |
DECIMAL(m,n) | DECIMAL(m,n) |
String(name, length) |
VARCHAR(n) | VARCHAR(n) |
Char(name, length) |
CHAR(n) | CHAR(n) |
Text(name) |
TEXT | TEXT |
MediumText(name) |
MEDIUMTEXT | TEXT |
LongText(name) |
LONGTEXT | TEXT |
Boolean(name) |
TINYINT(1) | BOOLEAN |
Date(name) |
DATE | DATE |
DateTime(name, precision) |
DATETIME | TIMESTAMP |
Timestamp(name, precision) |
TIMESTAMP | TIMESTAMP |
Time(name, precision) |
TIME | TIME |
Year(name) |
YEAR | SMALLINT |
Binary(name) |
BLOB | BYTEA |
Json(name) |
JSON | JSONB |
Enum(name, items...) |
ENUM | TEXT |
Set(name, items...) |
SET | TEXT |
Uuid(name) |
CHAR(36) | CHAR(36) |
IpAddress(name) |
VARCHAR(45) | VARCHAR(45) |
MacAddress(name) |
VARCHAR(17) | VARCHAR(17) |
Timestamps(precision) |
created_at + updated_at | created_at + updated_at |
SoftDeletes(column, precision) |
Nullable TIMESTAMP | Nullable TIMESTAMP |
RememberToken() |
VARCHAR(100) | VARCHAR(100) |
builder.String("name", 100).
Nullable(true). // Allow NULL
Default(migrate.StringExpr("default_value")). // Default value (string)
Default(migrate.RawExpr("CURRENT_TIMESTAMP")). // Default value (raw expression)
Comment("Username"). // Column comment (MySQL only)
Unique(). // Unique index
After("id"). // Place after a specific column (MySQL only)
First(). // Place as the first column (MySQL only)
Charset("utf8mb4"). // Character set (MySQL only)
Collation("utf8mb4_unicode_ci"). // Collation (MySQL only)
Unsigned(). // Unsigned (MySQL only, ignored on PostgreSQL)
Change() // Modify an existing column (instead of adding)PostgreSQL note: Modifiers marked "MySQL only" are silently ignored when using the PostgreSQL dialect.
builder.Index("", "name", "email") // Create index (name auto-generated)
builder.Index("idx_name", "name") // Create named index
builder.Unique("", "email") // Create unique index
builder.Primary("", "id") // Create primary key
builder.DropIndex("idx_name") // Drop index
builder.DropUnique("unique_name") // Drop unique index
builder.DropColumn("column1", "column2") // Drop columnsbuilder.Foreign("", "user_id").
References("id").
On("users").
OnDelete("CASCADE").
OnUpdate("CASCADE")
builder.DropForeign("foreign_key_name") // Drop foreign key// Drop table
m.Schema("20240102_001").Drop("temp_table")
m.Schema("20240102_002").DropIfExists("temp_table")
// Raw SQL migration
m.Schema("20240102_003").Raw("custom_table", func() []string {
return []string{
`CREATE TABLE custom_table (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(255))`,
}
})import "github.com/mylxsw/eloquent/query"
err := eloquent.Transaction(db, func(tx query.Database) error {
userModel := models.NewUserModel(tx) // Use tx instead of db
id, err := userModel.Save(ctx, models.UserN{
Name: null.StringFrom("Tom"),
})
if err != nil {
return err // Returning an error triggers automatic rollback
}
// ... more operations
return nil // Returning nil triggers automatic commit
})Panics within a transaction also trigger automatic rollback.
Eloquent includes a built-in event system for monitoring SQL execution, transactions, and migrations.
import "github.com/mylxsw/eloquent/event"
em := event.NewEventManager(event.NewMemoryEventStore())
event.SetDispatcher(em)
// Listen for SQL execution events (useful for logging, performance monitoring)
em.Listen(func(evt event.QueryExecutedEvent) {
fmt.Printf("[SQL] %s | args: %v | time: %s\n", evt.SQL, evt.Bindings, evt.Time)
})
// Listen for transaction events
em.Listen(func(evt event.TransactionBeginningEvent) {
fmt.Println("Transaction started")
})
em.Listen(func(evt event.TransactionCommittedEvent) {
fmt.Println("Transaction committed")
})
em.Listen(func(evt event.TransactionRolledBackEvent) {
fmt.Println("Transaction rolled back")
})
// Listen for migration events
em.Listen(func(evt event.MigrationStartedEvent) {
fmt.Printf("Running migration: %s\n", evt.SQL)
})| Event | Description |
|---|---|
QueryExecutedEvent |
Fired after each SQL query, includes SQL, bindings, and duration |
TransactionBeginningEvent |
Fired when a transaction starts |
TransactionCommittedEvent |
Fired when a transaction is committed |
TransactionRolledBackEvent |
Fired when a transaction is rolled back |
MigrationsStartedEvent |
Fired before a batch of migrations starts |
MigrationsEndedEvent |
Fired after a batch of migrations completes |
MigrationStartedEvent |
Fired before a single migration SQL is executed |
MigrationEndedEvent |
Fired after a single migration SQL is executed |
In addition to model-based operations, Eloquent provides low-level database operation APIs, suitable for complex queries or scenarios where you don't want to define a model.
import "github.com/mylxsw/eloquent"
dbOp := eloquent.DB(db)
ctx := context.TODO()
// Insert
id, err := dbOp.Insert(ctx, "users", query.KV{
"name": "Tom",
"email": "[email protected]",
})
// Query
results, err := dbOp.Query(ctx,
eloquent.Build("users").Select("id", "name").Where("age", ">", 18),
func(row eloquent.Scanner) (any, error) {
var id int64
var name string
err := row.Scan(&id, &name)
return map[string]any{"id": id, "name": name}, err
},
)
// Generic query (Go 1.18+)
type UserRow struct {
Id int64
Name string
}
users, err := eloquent.Query[UserRow](ctx, db,
eloquent.Build("users").Select("id", "name"),
func(row eloquent.Scanner) (UserRow, error) {
var u UserRow
err := row.Scan(&u.Id, &u.Name)
return u, err
},
)
// Raw SQL query
results, err := dbOp.Query(ctx,
eloquent.Raw("SELECT * FROM users WHERE age > ?", 18),
func(row eloquent.Scanner) (any, error) {
// ...
},
)
// Update
affected, err := dbOp.Update(ctx,
eloquent.Build("users").Where("id", 1),
query.KV{"name": "Jerry"},
)
// Delete
affected, err := dbOp.Delete(ctx, eloquent.Build("users").Where("id", 1))
// Execute a statement with no return value
err := dbOp.Statement(ctx, "TRUNCATE TABLE users")- _examples - Built-in complete example code
- tech-share - A simple web project demonstrating Eloquent in a real application