OOro

Query Builder

Model, table, raw, join, subquery, and terminal method reference.

Oro has three query entries:

db.Use[Product]()
db.Table("products")
db.Raw("select * from products where id = ?", id)

Model queries use Go field names. Table and Raw queries use database column names or SQL expressions.

Model query

product, err := db.Use[Product]().Where("Code", "P001").First(ctx)

Common methods:

Method Purpose
Where / OrWhere field conditions or condition objects
WhereGroup / OrWhereGroup parenthesized groups
WhereWhen conditional group
WhereRaw raw condition fragment
WhereColumn column comparison
WhereIn / WhereExists subquery conditions
Select fields, expressions, aggregates
With preload relations
For query through a relation
As main table alias
Join / LeftJoin / RightJoin / FullJoin joins
CrossJoin / JoinRaw special join forms
OrderBy / OrderByDesc / OrderByRaw ordering
GroupBy / Having / HavingRaw grouping
Limit / Offset paging primitives
LockForUpdate / LockForShare row locks
WithDeleted / OnlyDeleted soft-delete visibility
Cache / CacheKey / CacheTags query result cache
Timeout query-local timeout
SkipHooks / SkipEvents skip model hooks or global events

Table query

rows, err := db.Table("products").Where("price", ">=", 100).Get(ctx)

Table returns oro.Map by default. Use MapTo[T]() for DTOs:

views, err := db.Table("products").
    Select("id", "code", "price").
    MapTo[ProductView]().
    Get(ctx)

Raw query

rows, err := db.Raw("select * from "+db.TableName("products")+" where code = ?", code).Get(ctx)

Raw supports First, Get, MapTo[T], Stream, Exec, Cache, CacheKey, CacheTags, and Timeout.

Raw SQL does not automatically apply table prefixes. Use db.TableName.

Select

rows, err := db.Table("orders").
    Select(
        "status",
        oro.Count("*").As("total"),
        oro.Sum("amount").As("amount_sum"),
        oro.Raw("max(created_at) as last_created_at"),
    ).
    GroupBy("status").
    Get(ctx)

Model Select uses Go fields:

products, err := db.Use[Product]().Select("ID", "Code", "Price").Get(ctx)

Use oro.As(field, alias) for aliases.

Group and Having

rows, err := db.Table("orders").
    Select("status", oro.Count("*").As("total")).
    GroupBy("status").
    HavingRaw("count(*) > ?", 10).
    Get(ctx)

Having methods include Having, HavingColumn, HavingIn, HavingExists, and HavingRaw.

Join

Join conditions are expressed with a callback:

rows, err := db.Table("orders").As("o").
    LeftJoin("users", func(j *oro.Join) {
        j.As("u").OnColumn("u.id", "o.user_id")
    }).
    Where("o.status", "paid").
    Get(ctx)

Join source can be a table name or oro.Query(...).As(alias).

latestOrders := db.Table("orders").
    Select("user_id", oro.Raw("max(id) as last_order_id")).
    GroupBy("user_id")

rows, err := db.Table("users").As("u").
    LeftJoin(oro.Query(latestOrders).As("lo"), func(j *oro.Join) {
        j.OnColumn("lo.user_id", "u.id")
    }).
    Get(ctx)

Subqueries

paidOrders := db.Table("orders").Select("user_id").Where("status", "paid")

users, err := db.Table("users").WhereIn("id", oro.Query(paidOrders)).Get(ctx)
rows, err := db.From(oro.Query(paidOrders).As("po")).Get(ctx)

Terminal methods

Method Return
First(ctx) one row or nil
Find(ctx, id) primary-key lookup, model queries only
Get(ctx) slice
Count(ctx) int64
Exists(ctx) bool
Sum / Avg decimal result
Min[T] / Max[T] oro.Null[T]
Stream(ctx) streaming iterator
Chunk(ctx, size, fn) chunked read
Each(ctx, fn) row-by-row read
Paginate(size) paginator
Create / CreateMany / CreateManyResult writes
Upsert / UpsertMany conflict writes
Update / Delete mutation
Edit this page