Select

API

For the full list of supported methods, see API referenceopen in new window.

db.NewSelect().
    With("cte_name", subquery).

    Model(&strct).
    Model(&slice).

    Column("col1", "col2"). // quotes column names
    ColumnExpr("col1, col2"). // arbitrary unsafe expression
    ColumnExpr("count(*)").
    ColumnExpr("count(?)", bun.Ident("id")).
    ColumnExpr("(?) AS alias", subquery).
    ExcludeColumn("col1"). // all columns except col1
    ExcludeColumn("*"). // exclude all columns

    Table("table1", "table2"). // quotes table names
    TableExpr("table1 AS t1"). // arbitrary unsafe expression
    TableExpr("(?) AS alias", subquery).
    ModelTableExpr("table1 AS t1"). // overrides model table name

    Join("JOIN table2 AS t2 ON t2.id = t1.id").
    Join("LEFT JOIN table2 AS t2").JoinOn("t2.id = t1.id").

    WherePK(). // where using primary keys
    Where("id = ?", 123).
    Where("name LIKE ?", "my%").
    Where("? = 123", bun.Ident("id")).
    Where("id IN (?)", bun.In([]int64{1, 2, 3})).
    Where("id IN (?)", subquery).
    Where("FALSE").WhereOr("TRUE").
    WhereGroup(" AND ", func(q *bun.SelectQuery) *bun.SelectQuery {
        return q.WhereOr("id = 1").
            WhereOr("id = 2")
    }).

    Group("col1", "col2"). // quotes column names
    GroupExpr("lower(col1)"). // arbitrary unsafe expression

    Order("col1 ASC", "col2 DESC"). // quotes column names
    OrderExpr("col1 ASC NULLS FIRST"). // arbitrary unsafe expression

    Limit(100).
    Offset(100).

    For("UPDATE").
    For("SHARE").

    Scan(ctx)

Count rows

Bun provides Countopen in new window helper to generate count(*) queries:

count, err := db.NewSelect().Model((*User)(nil)).Count(ctx)

Because selecting and counting rows is a common operation, Bun also provides ScanAndCountopen in new window:

var users []User
count, err := db.NewSelect().Model(&users).Limit(20).ScanAndCount(ctx)
if err != nil {
	panic(err)
}
fmt.Println(users, count)

EXISTS

You can also use Existsopen in new window helper to use the corresponding EXISTS SQL operator:

exists, err := db.NewSelect().Model((*User)(nil)).Where("name LIKE '%foo%'").Exists(ctx)
if err != nil {
	panic(err)
}
if !exists {
	fmt.Println("such user does not exist")
}
SELECT EXISTS (SELECT * FROM users WHERE name LIKE '%foo%')

Joins

To select a book and manually join the book author:

book := new(Book)
err := db.NewSelect().
    Model(&book).
    ColumnExpr("book.*").
    ColumnExpr("a.id AS author__id, a.name AS author__name").
    Join("JOIN authors AS a ON a.id = book.author_id").
    OrderExpr("book.id ASC").
    Limit(1).
    Scan(ctx)
SELECT book.*, a.id AS author__id, a.name AS author__name
FROM books
JOIN authors AS a ON a.id = book.author_id
ORDER BY book.id ASC
LIMIT 1

To generate complex joins, use JoinOn:

q = q.
    Join("JOIN authors AS a").
    JoinOn("a.id = book.author_id").
    JoinOn("a.deleted_at IS NULL")
JOIN authors AS a ON a.id = book.author_id AND a.deleted_at IS NULL

Subqueries

You can use Bun queries (including INSERT, UPDATE, and DELETE queries) as a subquery:

subq := db.NewSelect().Model((*Book)(nil)).Where("author_id = ?", 1)

err := db.NewSelect().Model().TableExpr("(?) AS book", subq).Scan(ctx, &books)
SELECT * FROM (
  SELECT "book"."id", "book"."title", "book"."text"
  FROM "books" AS "book" WHERE (author_id = 1)
) AS book
Get insights and updates in your inbox: