Skip to content

Overview

Raiden utilize PostgREST to run query PostgreSQL database. Here is the quick example to get data from bookModel.

go
func (c *GetBooksController) Get(ctx raiden.Context) error {
  var books []models.Books

  err := db.
    NewQuery(ctx).
    From(models.Books{}).
    Select([]string{"id", "name", "isbn"}).
    Eq("isbn", "9786235266008").
    Get(&books)
  // SQL: select id, name, isbn from books where isbn = '9786235266008'
  // URL: /rest/v1/books?select=id,name,isbn&isbn=9786235266008

  if err != nil {
    fmt.Println(err)
    panic("Whoops!")
  }

  fmt.Println(books)
  fmt.Println(books[0].Id)
  fmt.Println(books[0].Name)
  fmt.Println(books[0].Isbn)

  return ctx.SendJson(books)
}

Retrieve Data

.Select()

go
var books []models.Books

err := db.NewQuery(ctx).
  From(models.Books{}).
  Select([]sring{"id", "slug", "name"}). 
  Get(&books)
// SQL: select id, slug, name from books
// URL: /rest/v1/books?select=id,slug,name

Alias

Use : to make an alias of column name with format alias_name:original_name.

go
var books []models.Books

err := db.NewQuery(ctx).
  From(models.Books{}).
  Select([]sring{"id", "title:name"}). 
  Get(&books)
// SQL: select id, name as title from books
// URL: /rest/v1/books?select=id,title:name

.Get() and .Limit()

Retrieve 10 rows of data.

go
var books []models.Books

err := db.NewQuery(ctx).
  From(models.Books{}).
  Limit(10)
  Get(&books)
// SQL: select * from books limit 10
// URL: "/rest/v1/books?select=*&limit=10"

.Single()

Get single row of data.

go
book := models.Books{}

err := db.NewQuery(ctx).
  From(models.Books{}).
  Eq("id", 1). 
  Single(&book)
// SQL: select * from books where id = 1 limit 1
// cURL: "/rest/v1/books?select=*&id=eq.1" -H "Accept: application/vnd.pgrst.object+json"

.Eq()

go
var books []models.Books

err := db.NewQuery(ctx).
  From(models.Books{}).
  Eq("id", 1). 
  Get(&books)
// SQL: select * from books where id = 1
// URL: /rest/v1/books?select=*&id=eq.1

.Neq()

go
var books []models.Books

err := db.NewQuery(ctx).
  From(models.Books{}).
  Neq("id", 1). 
  Get(&books)
// SQL: select * from books where id != 1
// URL: /rest/v1/books?select=*&id=neq.1

.Lt() & .Lte()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Lt("pages", 100). 
  Get(&books)
// SQL: select * from books where pages < 100
// URL: /rest/v1/books?select=*&id=lt.100

err = db.
  NewQuery(ctx).
  From(models.Books{}).
  Lte("pages", 100). 
  Get(&books)
// SQL: select * from books where pages <= 100
// URL: /rest/v1/books?select=*&id=lte.100

.Gt() & .Gte()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Gt("pages", 100). 
  Get(&books)
// SQL: select * from books where pages > 100
// URL: /rest/v1/books?select=*&id=gt.100

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Gte("pages", 100). 
  Get(&books)
// SQL: select * from books where pages >= 100
// URL: /rest/v1/books?select=*&id=gte.100

.In()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  In("id", []int{1, 2, 3}). 
  Get(&books)
// SQL: select * from books where id in (1, 2, 3)
// URL: /rest/v1/books?select=*&id=in.(1,2,3)

err = db.
  NewQuery(ctx).
  From(models.Books{}).
  In("slug", []string{"raiden", "supabase"}). 
  Get(&books)
// SQL: select * from books where slug in ('raiden', 'supabase')
// URL: /rest/v1/books?select=*&slug=in.(raiden,supabase)

.NotIn()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  NotIn("id", []int{1, 2, 3}). 
  Get(&books)
// SQL: select * from books where id not in (1, 2, 3)
// URL: /rest/v1/books?select=*&id=not.in.(1,2,3)

err = db.
  NewQuery(ctx).
  From(models.Books{}).
  NotIn("slug", []string{"raiden", "supabase"}). 
  Get(&books)
// SQL: select * from books where slug not in ('raiden', 'supabase')
// URL: /rest/v1/books?select=*&slug=not.in.(raiden,supabase)

.Like() & .Ilike()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Like("name", "%rai%"). 
  Get(&books)
// SQL: select * from books where name like '%rai%'
// URL: /rest/v1/books?select=*&name=like.*rai*

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Ilike("name", "%SuPa%"). 
  Get(&books)
// SQL: select * from books where name ilike '%SuPa%'
// URL: /rest/v1/books?select=*&name=ilike.*SuPa*

.NotLike() & .NotIlike()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  NotLike("name", "%rai%"). 
  Get(&books)
// SQL: select * from books where name not like '%rai%'
// URL: /rest/v1/books?select=*&name=not.like.*rai*

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  NotIlike("name", "%SuPa%"). 
  Get(&books)
// SQL: select * from books where name not ilike '%SuPa%'
// URL: /rest/v1/books?select=*&name=not.ilike.*SuPa*

.Is() & .NotIs()

Is() and NotIs() only accepts true, false, or nil.

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Is("is_active", true). 
  Get(&books)
// SQL: select * from books where is_active is true
// URL: /rest/v1/books?select=*&is_active=is.true

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  NotIs("is_active", true). 
  Get(&books)
// SQL: select * from books where is_active not is true
// URL: /rest/v1/books?select=*&is_active=not.is.true

.OrderAsc() & .OrderDesc()

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  OrderAsc("created_at") 
  Get(&books)
// SQL: select * from books order by created_at asc
// URL: /rest/v1/books?select=*&order=created_at.asc

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  OrderDesc("created_at") 
  Get(&books)
// SQL: select * from books order by created_at desc
// URL: /rest/v1/books?select=*&order=created_at.desc

Insert

go
payload := models.Products{name: "Chair", price: 20}

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Insert(&payload, nil)
// insert into products (name, price) values ('Chair', 20)

Update

go
payload := models.Products{slug: "raiden"}

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Eq("id", 1).
  Update(payload, nil)
// SQL: update products set slug = 'raiden' where id = 1

Delete

go
err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Eq("id", 1).
  Delete()
// SQL: delete from products where id = 1

Upsert

go
id1 := int64(6)
name1 := "Cake"
slug1 := "cake"
rating1 := int64(4)

id2 := int64(42)
name2 := "Water"
slug2 := "water"
rating2 := int64(5)

products := []models.Products{
  {
    Id:        id1,
    Name:      &name1,
    Slug:      &slug1,
    Rating:    &rating1,
  },
  {
    Id:        id2,
    Name:      &name2,
    Slug:      &slug2,
    Rating:    &rating2,
  },
}

// Convert to []interface{}
var payload = make([]interface{}, len(products))
for i, v := range teams {
  payload[i] = v
}

opt := db.UpsertOptions{
  OnConflict: db.MergeDuplicates, // or db.IgnoreDuplicates
}

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  Upsert(payload, opt) 

// SQL:
// insert into products (id, name, slug, rating)
// values (6, 'Cake', 'cake', 4), (6, 'Water', 'water', 4)
// on conflict(id)
// do update set
//   price = excluded.price,
//   quantity = excluded.quantity;

Relationship

Get Relations

By using .With(), you can get the relation of a model.

go
var books []models.Books

res := db.
  NewQuery(ctx).
  From(models.Books{}).
  With("Authors", nil). // models.Authors{}
  With("Publishers", nil). // models.Publishers{}
  Get(&books)

// SQL:
// select books.*, users.*, publishers.* from books
// inner join users on books.author_id = users.id
// inner join publishers on books.published_id = publishers.id;

// URL: /rest/v1/books?select=*,users(*),publishers(*)

Nested Relations

go
var books []models.Books

res := db.
  NewQuery(ctx).
  From(models.Books{}).
  With("Authors.Teams.Orgs", nil).
  Get(&books)

// URL: /rest/v1/books?select=*,users(*,teams(*,orgs(*)))

Column Selections

go
var books []models.Books

err := db.
  NewQuery(ctx).
  From(models.Books{}).
  With(
    "Publishers.Orgs",
    map[string][]string{
      "publishers": {"id", "name"},
      "orgs":       {"id", "name"},
    },
  ).
  Get(&books)

// URL: /rest/v1/books?select=*,publishers(id,name,orgs(id,name))

Foreign Keys

Assume you have this tables

sql
create table
  public.orders (
    id bigint generated by default as identity not null,
    created_at timestamp with time zone not null default now(),
    billing_id bigint null,
    shipping_id bigint null,
    constraint orders_pkey primary key (id),
    constraint orders_shipping_id_fkey foreign key (shipping_id) references addresses (id),
    constraint orders_billing_id_fkey foreign key (billing_id) references addresses (id)
  ) tablespace pg_default;

create table
  public.addresses (
    id bigint generated by default as identity not null,
    created_at timestamp with time zone not null default now(),
    name text not null,
    constraint addresses_pkey primary key (id)
  ) tablespace pg_default;

Since the orders table has two foreign keys to the addresses table, a foreign key join is ambiguous and you will get an error.

go
// Error
orders := []models.Orders{}

err := db.
  NewQuery(ctx).
  From(models.Orders{}).
  With("Addresses", nil).
  Get(&orders)

To successfully join orders with addresses you need to add explicit foreign key by adding ! symbol with format table!foreign_key.

go
orders := []models.Orders{}

err := db.
  NewQuery(ctx).
  From(models.Orders{}).
  With(
    "Addresses",
    map[string][]string{
      "addresses!shipping_id": {"*"},
    },
  ).
  Get(&orders)

// URL: /rest/v1/orders?select=*,addresses!shipping_id(*)

To add the shipping address and billing address you need to use alias.

go
orders := []models.Orders{}

err := db.
  NewQuery(ctx).
  From(models.Orders{}).
  With(
    "Addresses",
    map[string][]string{
      "shipping_address:addresses!shipping_id": {"*"},
    },
  ).
  With(
    "Addresses",
    map[string][]string{
      "billing_address:addresses!billing_id": {"*"},
    },
  ).
  Get(&orders)

// URL: /rest/v1/orders?select=*,shipping_address:addresses!shipping_id(*),billing_address:addresses!billing_id(*)

Released under the MIT License.