I am having trouble making queries in GORM, like joins - go

type Books_model struct {
// gorm.Model
Book_id string `json:"book_id" gorm:"primarykey"`
Title string `json:"title"`
Author string `json:"author"`
Gender string `json:"gender"`
Publisher string `json:"publisher"`
Country string `json:"country"`
Rating_model Rating_model `gorm:"foreignKey:Books_rating_id;AssociationForeignKey:Books_rating_id"`
// ;AssociationForeignKey:Books_rating_id
Reviews_model Reviews_model `gorm:"foreignKey:Books_model_id;AssociationKey:Books_model_id"`
}
type Rating_model struct {
gorm.Model
Books_rating_id string `json:"books_rating_id" `
`gorm:"foreignKey:book_id;references:Book_id"`
Rating string `json:"rating"`
}
type Reviews_model struct {
gorm.Model
Ret_id string `json:"ret_id"`
Books_model_id string `json:"books_model_id"`
Review string `json:"review"`
}
##############################
My problem is that i have made foreign keys and i have make joins to combine the tables like book id 3 has rating of 4 and review is this, but i am trying no query is working,Gorm is really hard to understand.

Related

How do I store the data from DTO Gorm

I am using golang fiber and GORM. I am trying to store the data from DTO. For example, I have created a post entity and post dto like below.
type User struct {
gorm.Model
Name string
Address string
Phone string
}
This is my DTO
type PostDto struct {
Name string `json:"name"`
Address string `json:"address"`
Phone string `json:"phone"`
}
I am trying to store the data like below
var postDto models.PostDto
c.BodyParser(&postDto)
err := database.DB.Model(models.User{}).Create(&postDto).Error
fmt.Println(err.Error())
But I am getting the below error
panic: reflect: call of reflect.Value.Field on string Value
Could anyone help to resolve this issue?
Thanks in advance
I don't know what you are doing? this is go language, not java, why do you define two structs?
You can use tag to complete that you want.
type User struct {
gorm.Model `json:"-" gorm:"-"`
Name string `json:"name" gorm:"column:name"`
Address string `json:"address" gorm:"column:address"`
Phone string `json:"phone" gorm:"column:phone"`
}
var user User
err := database.DB.Model(User{}).Create(&user).Error
fmt.Println(err.Error())
User and PostDto structures are not same, using one model to get and save data from another is wrong.
Either create a function to convert from PostDto to User, adn use its output in Create
func (postDTo PostDTo) ToUser() *User {
return &User{Name: postDTo.Name, Address: postDTo.Address, Phone: postDTo.Phone}
}
OR, as User and PostDto structs are so similar, add json ignore to gorm.Model in User and use it instead of PostDto
type User struct {
gorm.Model `json:"-"`
Name string `json:"name"`
Address string `json:"address"`
Phone string `json:"phone"`
}
var postData models.User
c.BodyParser(&postData)

How can I change the fields of a struct's json marshal?

tl;dr
How can I dynamize the JSON fields of a struct?
I am using gorm as the ORM. I have my model definition as a struct:
type UserAccessToken struct {
Id uint `gorm:"primaryKey" json:"-"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt gorm.DeletedAt `json:"deletedAt"`
User User `gorm:"constraint:OnDelete:CASCADE" json:"-"`
UserId uint `gorm:"not null" json:"-"`
IpAddress string `gorm:"not null" json:"ipAddress"`
Token string `gorm:"not null" json:"token"`
}
I have multiple endpoints and I want to use different fields of the struct serialized on each endpoint.
For example, on POST /user-access-tokens/ user will be basic authenticated and a new access token will be created and returned on the response. However, on GET /user-access-tokens/ list API endpoint, the response will be a list of the UserAccessTokens, but the Token won't be on the response. And I am planning to create another endpoint only to be used by the administration interface, and all fields will be available there.
There are two I can think of:
Creating a different struct and reading from the database into this struct.
Adding a method like Map(scenario string) to the model struct which will create a map of the struct according to scenario, but in this case, I also need to add function to handle multiple instances of the struct.
What is the recommended way for this?
You can use another struct:
type UserAccessstruct {
Id uint `gorm:"primaryKey" json:"-"`
CreatedAt time.Time `json:"createdAt"`
DeletedAt gorm.DeletedAt `json:"deletedAt"`
User User `gorm:"constraint:OnDelete:CASCADE" json:"-"`
UserId uint `gorm:"not null" json:"-"`
IpAddress string `gorm:"not null" json:"ipAddress"`
}
type UserAccessToken {
UserAccessstruct
Token string `gorm:"not null" json:"token"`
}
func Get() {
var userAccess UserAccessToken
db.Select(selectQuery).First(&userAccess)
return userAccess // Full return
return userAccess.UserAccessstruct // Inner struct without token
}

Specify many-to-many relationship in buffalo model

Please does anyone know how to specify a many-to-many relationship in buffalo models?
gobuffalo many_to_many ...
type Organization struct {
ID int `json:"id" db:"id"`
Users Users `many_to_many:"user_organizations"`
}
type User struct {
ID int `json:"id" db:"id"`
Organizations Organizations `many_to_many:"user_organizations" json:"-"`
}
type UserOrganization struct {
ID int `json:"id" db:"id"`
OrganizationID int `json:"organization_id" db:"organization_id"`
UserID int `json:"user_id" db:"user_id"`
User User `belongs_to:"users"`
Organization Organization `belongs_to:"organizations"`
}
Each of these structs are in their own models/*.go file
https://gobuffalo.io/en/docs/db/relations

How to init and insert struct with foreign key constraint into db using GORM

I am trying to create a rest API with golang. Each time a user is created, I would like to create a 'Profile' which is associated with that user.
My initial thought was to first create the user, and then separately create the profile referencing the user ID and inserting that into the database.
I'm not sure if this kind of thinking aligns with the way go should be used as i'm just starting with the language.
Using below code, I create the user, but cannot create the profile. I receive this error: using unaddressable value
var db *gorm.DB
func GetDB() *gorm.DB {
return db
}
type User struct {
gorm.Model
Email string `gorm:"type:varchar(100);unique_index"`
Password string `json:"password"`
Name string `json:"name"`
Token string `json:"token";sql:"-"`
}
type Profile struct {
gorm.Model
User User `gorm:"foreignkey:UserRefer"` // use UserRefer as foreign key
UserRefer uint
FirstName string `gorm:"default:'John'"`
LastName string `gorm:"default:'Doe'"`
Description string `gorm:"default:'Mysterious'"`
}
func (user *User) Create() (map[string]interface{}) {
if resp, ok := user.Validate(); !ok {
return resp
}
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(user.Password), bcrypt.DefaultCost)
user.Password = string(hashedPassword)
GetDB().Create(user)
profile := Profile{}
profile.UserRefer = user.ID
GetDB().Create(profile)
if user.ID <= 0 {
return u.Message(false, "Failed to create account, connection error.")
}
response := u.Message(true, "Account has been created")
response["user"] = user
return response
}
I'm hoping someone will be able to help me understand what is going wrong here?
You should pass a pointer on gorm's Create method to get your model Filled after creation...
GetDB().Create(&profile)
But, as is showed in https://gorm.io/docs/associations.html gorm Auto create the associations.
You can change your models, like so... (I am supposing that User and Profile has a 1..1 relation ok?)
And everything will get done automatically
type User struct {
gorm.Model
Email string `gorm:"type:varchar(100);unique_index"`
Password string `json:"password"`
Name string `json:"name"`
Token string `json:"token";sql:"-"`
Profile Profile
ProfileID uint
}
type Profile struct {
gorm.Model
UserID uint
FirstName string `gorm:"default:'John'"`
LastName string `gorm:"default:'Doe'"`
Description string `gorm:"default:'Mysterious'"`
}

How to access gorm.Model.ID?

So gorm.Model provides some base properties or fields:
ID uint `json:"-" gorm:"primary_key"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
DeletedAt *time.Time `json:"-" sql:"index"`
and you can use it as so
type User struct {
gorm.Model
Name string
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // set field size to 255
}
So when I was working on my Model Controller(s) for delete (or anything where I needed to compare the ID)
This does not work, give me an error:
c.Ctx.DB.Delete(&models.Address{ID: id})
unknown field 'ID' in struct literal of type
github.com/NlaakStudios/PASIT/models".Address
And, this does not work, give me an error:
c.Ctx.DB.Delete(&models.Address{gorm.Model.ID: id})
invalid field name gorm.Model.ID in struct initializer id int
If I remove the gorm.Model and define the field myself in each model ... it works.
type User struct {
ID uint `json:"-" gorm:"primary_key"`
CreatedAt time.Time `json:"-"`
UpdatedAt time.Time `json:"-"`
DeletedAt *time.Time `json:"-" sql:"index"`
Name string
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // set field size to 255
}
How do I access those four base fields?
You're very close in your last example. You can remove the gorm.Model inheritance from your struct if you want/need (I personally do that for clarity), but to access that value you'd just need to build up your struct a little more. For example...
type Address struct {
gorm.Model
Name string
Email string `gorm:"type:varchar(100);unique_index"`
Role string `gorm:"size:255"` // set field size to 255
}
c.Ctx.DB.Delete(&models.Address{gorm.Model: gorm.Model{ID: id}})
Give that a try and see if that works for you. Alternatively revert to your method without inheriting the gorm.Model
I worked with this: removing package Name 'gorm'
c.Ctx.DB.Delete(&models.Address{Model: gorm.Model{ID: id}})
looks like this is an interesting question - but of category 'selfmade problem':
what about
c.Ctx.DB.Delete(&model.Address{}, id)
then you can keep the benefits (or not - depends on taste) of gorm.Model

Resources