Reputation:
I can't figure how to properly write a query that will select only those entries where condition is applied against relations table.
My many-to-many schema looks like this Topics
- TopicPosts
- Posts
. I want to query all TopicPosts
where Post
is not private or is belongs to the current user. I'm doing it like this:
topicPosts := []model.TopicPost{}
h.DB.
Where("topic_id = ?", id).
Preload("Post", func(db *gorm.DB) *gorm.DB {
return db.Not("is_private = ? AND user_id != ?", "true", currentUser.ID)
}).
Preload("Post.Tags").
Find(&topicPosts)
As expected it returns all TopicPosts
but does not eagerly load Posts
with a given condition. I then manually filter them out:
publicTopicPosts := []model.TopicPost{}
for _, p := range topicPosts {
if p.Post.ID != 0 {
publicTopicPosts = append(publicTopicPosts, p)
}
}
I realise this is a subpar solution, I'm not very good with SQL but I think it should be possible to achieve within a single query. I would appreciate any help. I'm using Postgres if it matters.
Upvotes: 3
Views: 13099
Reputation: 207
You can use this method
db.Preload("Post", "is_private = ? AND user_id != ?", "true", currentUser.ID).Find(&topicPosts)
Upvotes: 7
Reputation: 51
From my experience the most appropriate way to do that with GORM is by utilizing SubQueries:
topicPosts := []model.TopicPost{}
DB.GetDB().
Where("topic_id = ? AND post_id IN (?)", id,
DB.GetDB().Table("posts").
Select("id").
Not("is_private = ? AND user_id != ?", "true", currentUser.ID)).
SubQuery()).
Preload("Post").
Find(&topicPosts)
Upvotes: 5