I have a problem with time in postgresql table with generic GORM model
gorm.Model
with fields
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
all dates in table have format 2020-04-21 22:05:07.067446
Please Can I change to timstamp(LONG) or something without .067446
Thanks for any Help
You can use BeforeCreate and BeforeUpdate hook for gorm.Model to manually set the value for the database.
Create BaseModel since you can't use type receiver for other package type.
type BaseModel struct {
gorm.Model
}
Then manually set the value CreatedAt and UpdatedAt without nanoseconds
func (b *BaseModel) BeforeCreate() (err error) {
b.CreatedAt = time.Unix(time.Now().Unix(), 0) // Calculate without nanosec
return
}
func (b *BaseModel) BeforeUpdate() (err error) {
b.UpdatedAt = time.Unix(time.Now().Unix(), 0) // Calculate without nanosec
return
}
And then use BaseModel in your DB Model
type Data struct {
BaseModel
Name string
}
Related
i'm new to Golang and facing retriving child table data that container id refer to parent table id. In the documentation shows that only the parent can retrieve child using preload method but didn't show how to retrieve reversed back.
(one to many relationship)
Parent Table
type User struct {
Id uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()" json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
Email string `json:"email"`
Gender string `json:"gender"`
Alias string `json:"alias"`
RefreshToken *string `json:"refresh_token,omitempty"`
AccessToken *string `json:"access_token,omitempty"`
DateOfBirth *time.Time `json:"date_of_birth"`
LastLoggedIn *time.Time `json:"last_logged_in"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
Account []Account `json:"account"`
}
Child Table
type Account struct {
Id uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()" json:"id"`
Name string `json:"name"`
Balance float32 `json:"balance"`
UserId string `json:"user_id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
Was hoping that can return json like this:
[{
"Id":"xxx",
....
User: {"Id":"xxx"}
}]
I'm not sure is this possible or not but prisma did it, sorry for disturb your time and have a nice day!
You can add which fields you want to preload and how deep to go. Check nested preloading.
In your case, you could do it like the below.
add User field to Account struct:
type Account struct {
Id uuid.UUID `gorm:"type:uuid;default:gen_random_uuid()" json:"id"`
Name string `json:"name"`
Balance float32 `json:"balance"`
UserId string `json:"user_id"`
User *User `json:"user"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
in your method:
var users []User
// Preload Account field inside User struct, and User field inside Account struct
err := db.Preload("Account.User").Find(&users).Error
I am building a simple REST API for my blog using Golang. I store my posts in MongoDB, so, when I retrieve some record, I have to serialize (not sure if it's a right term) to native Golang type (struct). Since I have multiple endpoints with different return types, it seems like I have to have a bunch of similar types with difference in only one field. This needed when I perform $lookup operation, which is basically the analog of join operation in relational DBs.
I think the problem I meant will be clear from example:
type Post struct {
title string
author string
category string
}
type Author struct {
firstname string
lastname string
}
type Category struct {
name string
parent Category
}
type PostWithAuthor struct {
title string
author Author
category string
}
type PostWithCategory struct {
title string
author string
category Author
}
type PostWithAuthorAndCategory struct {
title string
author Author
category Category
}
func getPost() (Post) {
}
func getPostWithCategory() (PostWithCategory) {
}
func getPostWithAuthor() (PostWithAuthor) {
}
func getPostWithAuthorAndCategory() (PostWithAuthorAndCategory) {
}
You can use a struct inside another struct.
type Post struct {
Title string
Author Author
Category Category
}
type Author struct {
FirstName string
LastName string
}
type Category struct {
Name string
Parent *Category
}
// Query via `gorm`
var posts []Post
db.Where(&Post{Category: Category{Name: "food"}}).Find(&posts)
I'm getting the following error while migrating
2021/06/08 11:01:40 /go/pkg/mod/gorm.io/driver/postgres#v1.1.0/migrator.go:157 ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index" (SQLSTATE 23505)
[18.041ms] [rows:0] CREATE TABLE "users" ("id" bigserial,"created_at" timestamptz,"updated_at" timestamptz,"deleted_at" timestamptz,"email" text UNIQUE,"password" text,PRIMARY KEY ("id"))
2021/06/08 11:01:40 Migration error: ERROR: duplicate key value violates unique constraint "pg_type_typname_nsp_index" (SQLSTATE 23505)
FAIL github.com/dhis2-sre/instance-manager-api/tests/handler/authentication 0.059s
I suspect that there's an issue with the way I've defined my model. Possible in relation to how I define the relationship between User and Group.
type Group struct {
gorm.Model
Name string `gorm:"unique;"`
Users []User `gorm:"many2many:user_groups;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Instances []Instance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
ClusterConfiguration ClusterConfiguration `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
type ClusterConfiguration struct {
gorm.Model
GroupID uint
KubernetesConfiguration SopsPair `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
// AWSCredentials SopsPair
// AWSConfiguration SopsPair
}
type SopsPair struct {
gorm.Model
ClusterConfigurationID uint
Data string
Format string
}
type Instance struct {
gorm.Model
Name string `gorm:"unique;"`
UserID uint
GroupID uint
StackID uint
RequiredParameters []InstanceRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requiredParameters,omitempty"`
OptionalParameters []InstanceOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"optionalParameters,omitempty"`
}
type InstanceRequiredParameter struct {
gorm.Model
InstanceID uint `gorm:"index:idx_instance_required_parameter,unique"`
StackRequiredParameterID uint `gorm:"index:idx_instance_required_parameter,unique"`
StackRequiredParameter StackRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
Value string
}
type InstanceOptionalParameter struct {
gorm.Model
InstanceID uint `gorm:"index:idx_instance_optional_parameter,unique"`
StackOptionalParameterID uint `gorm:"index:idx_instance_optional_parameter,unique"`
StackOptionalParameter StackOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"-"`
Value string
}
type Stack struct {
gorm.Model
Name string `gorm:"unique;"`
RequiredParameters []StackRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requiredParameters,omitempty"`
OptionalParameters []StackOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"optionalParameters,omitempty"`
Instances []Instance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
type StackRequiredParameter struct {
gorm.Model
StackID uint `gorm:"index:idx_name_required_parameter,unique"`
Name string `gorm:"index:idx_name_required_parameter,unique"`
}
type StackOptionalParameter struct {
gorm.Model
StackID uint `gorm:"index:idx_name_optional_parameter,unique"`
Name string `gorm:"index:idx_name_optional_parameter,unique"`
}
type User struct {
gorm.Model
Email string `gorm:"unique;"`
Password string `json:"-"`
Groups []Group `gorm:"many2many:user_groups;constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
Instances []Instance `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
}
Please let me if I should post additional parts of my code.
let say one teacher has many students and student only has one teacher, how to implement it on Gorm Golang ?
my opinion is
type Teacher struct {
gorm.Model
Name string
Student []Student
}
type Student struct {
gorm.Model
Name string
}
is those correct ?? and if not how to make it to be associated? and how about if we query it to create ? should I create another StudentID on it ?
type Teacher struct {
gorm.Model
Name string
}
type Student struct {
gorm.Model
Name string
TeacherId uint `gorm:"TYPE:integer REFERENCES teachers;index"`
}
gorm tell in the documentation that "Base model definition gorm.Model, including fields ID, CreatedAt, UpdatedAt, DeletedAt, you could embed it in your model, or only write those fields you want":
// Base Model's definition
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
// Add fields `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`
type User struct {
gorm.Model
Name string
}
// Only need field `ID`, `CreatedAt`
type User struct {
ID uint
CreatedAt time.Time
Name string
}
Following the documentation, I expect to have only one definition of User, so I create an object like that:
type User struct {
gorm.Model
ID uint
CreatedAt time.Time
Name string
}
But if I do a DB.CreateTable(&User{}), I get the following errors from postgres:
(pq: column "id" specified more than once)
(pq: column "created_at" specified more than once)
So I have to have two different objects :
type CreateUser struct {
gorm.Model
Name string
}
type RetrieveUser struct {
gorm.Model
ID uint
CreatedAt time.Time
Name string
}
So I can do a DB.CreateTable(&CreateUser{})
It is very ugly and I must be missing something, any idea?
Ok, just read the code behind gorm.Model and I got my answer.
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time `sql:"index"`
}
It means I just learned how inheritance works in go !