Gorm extra where 1 <> 1 in many2many - go

I have two models (structs). User and Group. Those models have many to many relationships.
When I try to create query db.Unscoped().Model(&group).Related(&users, "Users") this returns:
SELECT users.* FROM users INNER JOIN user_groups ON user_groups.owner_id = users.id WHERE (1 <> 1)
The entities are:
type Group struct {
gorm.Model
ID uint `json:"id"`
Name string `json:"name"`
Users []User `gorm:"many2many:user_groups;association_jointable_foreignkey:owner_id"`
}
type User struct {
...
Groups []Group `gorm:"many2many:user_groups;association_jointable_foreignkey:group_id"`
}
Handler
users := []models.User{}
group := models.Group{}
db.Unscoped().Model(&group).Related(&users, "Users")
I don't know the reason to generate extra where.

The problem is fixed.
I have eliminated gorm.Model in struct:
type Group struct {
ID uint `json:"id"`
Name string `json:"name"`
Users []User `gorm:"many2many:user_groups;association_jointable_foreignkey:owner_id"`
}
And In the query:
db.Model(&group).Related(&users)
Regards.

Related

Gorm joined tables selects only few field

I have some of this code
type User struct {
Id uint `gorm:"column:id"`
Name string `gorm:"column:name"`
WalletId uint `gorm:"column:wallet_id"`
Wallet Wallet `gorm:"foreignkey:club_id"`
}
type Wallet struct {
Id uint `gorm:"column:id"`
Money uint `gorm:"column:money"`
Valute string `gorm:"column:valute"`
}
I can query users and their wallets like this
var users []users
db.Joins("Wallet").Find(&users)
this will generate stmt like this
SELECT user.id, user.name, user.wallet_id, wallet.id, wallet.Money, wallet.Valute from user join wallet on user.wallet_id = wallet.id
I need to query all users and only `Valute' field from their wallets
I want to use a gorm like
var users []users
db.Joins("Wallet", db.Select("Valute")).Find(&users)
for generate this stmt
SELECT user.id, user.name, user.wallet_id, wallet.Valute from user join wallet on user.wallet_id = wallet.id
For choose a wallet field. But it doesn't work at all. Although there is such a use in the function annotation
// Joins specify Joins conditions
// db.Joins("Account").Find(&user)
// db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu#example.org").Find(&user)
// db.Joins("Account", DB.Select("id").Where("user_id = users.id AND name = ?", "someName").Model(&Account{}))
func (db *DB) Joins(query string, args ...interface{}) (tx *DB) {
In eager loading by Preload i can choose fields like
db.Limit(1000).Preload("Wallet",
func(db *gorm.DB) *gorm.DB {
return db.Select("valute")
},
).Find(&users)
But this isnt good usage for me, it has a bad perfomance when querying one object. I like to know how can i do the same with Joins
PS: I dont want to use a lightweigh model for wallet which queries only valute, i want to use single model for db presentation
I also want Gorm to support this feature but the best solution I came up with is Smart Select but it requires us to manually write query and select fields
type CustomUser struct {
Id uint `gorm:"column:id"`
Name string `gorm:"column:name"`
Valute string `gorm:"column:valute"`
}
var users []CustomUser
db.Raw("SELECT users.id, users.name, Wallet.valute FROM `users` LEFT JOIN `wallets` `Wallet` ON `users`.`wallet_id` = `Wallet`.`id`").Find(&users)

How to join multiple tables using GORM without Preload

I currently have 3 tables with relation between them through GORM. I'm looking to query the sellers with all informations about the relation.
Here's my entities:
type ShopType struct {
ID uint `gorm:"primarykey" json:"id"`
Name string `json:"name" xml:"name" form:"name" query:"name"
}
type Shop struct {
ID uint `gorm:"primarykey" json:"id"`
Name string `json:"name" xml:"name" form:"name" query:"name"
ShopType ShopType `gorm:"ShopTypeID;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;" json:"-"`
}
type Seller struct {
ID uint `gorm:"primarykey" json:"id"`
Firstname string `json:"firstname" xml:"firstname" form:"firstname" query:"firstname"
Lastname string `json:"lastname" xml:"lastname" form:"lastname" query:"lastname"
Shop Shop `gorm:"foreignKey:ShopID;constraint:OnUpdate:CASCADE,OnDelete:RESTRICT;" json:"-"`
}
It's not possible to use Joins instead of Preload like :
db.Model(&models.Seller{}).Joins("Shop").Joins("Shop.ShopType").Find(&results)
?
I have tried this but it doesn't work.
Also I have tried :
db.Model(&models.Seller{}).Joins("JOIN shops s on s.id = sellers.shop_id").Joins("JOIN shop_types st on st.id = s.shop_type_id")
It's work but it didn't fill the props of the Shop and ShopType entities, only the informations about the sellers are filled.
I'm looking to joins my entities using Joins instead of Preload because I want add some clauses to my query like : .Where('Shop.ShopType.Name IN (?)') and that's not possible with the Preload method.
You are almost there with the second query, you can combine the Preload and Where functions with it.
var sellers []Seller
db.Joins("JOIN shops s on s.id = sellers.shop_id").
Joins("JOIN shop_types st on st.id = s.shop_type_id").
Preload("Shop.ShopType").
Where("st.name IN (?)", []string{"Store1", "Store2"}).
Find(&sellers)

Accessing column in junction table in GORM

I have three tables users, todos and user_todos:
type User struct {
ID uint64
Email string
Todos []Todo `gorm:"many2many:user_todos"`
}
type Todo struct {
ID uint64
Title string
}
type UserTodos struct {
UserID uint64
TodoID uint64
Done bool
}
Now I want to get all users with all todos. db.Preload("Todos").Find(&users) does the trick for that.
But what if I want to get all todos and see if they are already done by the user?
I tried to create a SQL view checked_todos which joins the user_todos table and exchange the Todos attribute in the User struct with a CheckedTodo, which just extends Todo with a boolean field. Preloading never access the right table.
Couldn't find any hints in the GORM documentation how to access the columns in the junction table.
You might be able to achieve what you want with custom preloading. Two options you might want to try:
Option 1
db.Preload("Todos", func(grm *gorm.DB) *gorm.DB {
return grm.Where("user_todos.done = 1")
}).Find(&users)
Option 2
db.Preload("Todos", func(grm *gorm.DB) *gorm.DB {
return grm.Joins("INNER JOIN user_todos ON user_todos.todo_id = todos.id AND user_todos.done = 1")
}).Find(&users)

Didn't get Delete User records based on ID

I'm using Go with Gorm many2many association from User and Role tables.
type User struct {
//gorm.Model
ID int64 `json:"id" gorm:"primary_key"`
Active sql.NullString ` json:"active " `
Email string `json:"email"`
FullName string `json:"full_name"`
Password string `json:"password"`
Username string `json:"username"`
Groups string `json:"groups"`
Otp string `json:"otp"`
CreatedTimeStamp time.Time `json:"created_time_stamp"`
UpdateTimeStamp time.Time `json:"update_time_stamp"`
LastLogin time.Time `json:"last_login"`
UserCount uint `json:"user_count" `
Roles []Role `gorm:"many2many:user_roles;"`
}
type Role struct {
//gorm.Model
ID int64 `json:"id" gorm:"primary_key"`
Name string `json:"name"`
Users []User `gorm:"many2many:user_roles"`
}
using below code for delete user records and roles based on user id.
var roles []Role
db.Model(Role{}).Where("Name = ?", "ROLE_ADMIN").Take(&roles)
newUser := &User{
Email: user.Email,
FullName: user.FullName,
Username: user.Username,
Groups: groupCreation(user.Username),
Password: EncodePassword(user.Password),
CreatedTimeStamp: time.Now(),
UpdateTimeStamp: time.Now(),
LastLogin: time.Now(),
Roles: roles
}
db.Save(newUser)
**db.Model(&user).Association("Role").Delete(&newUser)**
Once executed last statement but didn't get delete(no impact) records from tables users and user_roles.
Kindly suggest me what is issue.
This code:
db.Model(&user).Association("Role").Delete(&newUser)
by the Gorm documentation:
Remove the relationship between source & arguments if exists, only delete the reference, won’t delete those objects from DB.
You need to use the Delete with Select https://gorm.io/docs/associations.html#Delete-with-Select
So actually it should be:
db.Select("Role").Delete(&newUser)

How can I remove a 'Belongs To' association in jinzhu/gorm

Can anyone help me, how to remove a belongs to association in go-gorm?
Here are my simple models:
type User struct {
gorm.Model
Name string
FirstName string
}
type Customer struct {
Notes []Note `gorm:"polymorphic:Owner;"` // other models can have notes as well
}
type Note struct {
gorm.Model
User User `json:"-"`
UserID uint
OwnerID uint
OwnerType string
}
For "Has many" and "Many to many" associations I can remove the relations. In this example, this works:
db.Model(&customer).Association("Notes").Delete(&note)
However, if I try following:
db.Model(&note).Association("User").Delete(&user)
I get a pointer error:
panic: runtime error: index out of range
... src/github.com/jinzhu/gorm/association.go:242 +0x21ce
The ''user'' and ''note'' objects exist and the relation is there (UserID is set to 1 in the database).

Resources