【问题标题】:GORM Preload by condition in a related tableGORM 在相关表中按条件预加载
【发布时间】:2020-09-25 13:01:46
【问题描述】:

我不知道如何正确编写一个查询,该查询将只选择那些条件适用于关系表的条目。 我的多对多模式看起来像这样Topics - TopicPosts - Posts。我想查询所有TopicPosts,其中Post 不是私有的或属于当前用户。我这样做是这样的:

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)

正如预期的那样,它返回所有TopicPosts,但不会急切地加载给定条件的Posts。然后我手动过滤掉它们:

publicTopicPosts := []model.TopicPost{}
for _, p := range topicPosts {
    if p.Post.ID != 0 {
        publicTopicPosts = append(publicTopicPosts, p)
    }
}

我意识到这是一个低于标准的解决方案,我不太擅长 SQL,但我认为应该可以在单个查询中实现。我将不胜感激任何帮助。如果重要的话,我正在使用 Postgres。

【问题讨论】:

  • 在运行查询之前调用h.DB.Debug().Where ... 以查看正在执行的 SQL 怎么样?
  • 另外,您可能已经完成了此操作,但为简洁起见未显示,但请务必在运行查询时检查 .Error 字段,以了解您可以信任所拥有内容的内容加载。 err := h.DB.Where()....Find(&dest).Error

标签: go go-gorm


【解决方案1】:

根据我的经验,使用 GORM 最合适的方法是使用子查询:

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)

【讨论】:

    【解决方案2】:

    你可以用这个方法

    db.Preload("Post", "is_private = ? AND user_id != ?", "true", currentUser.ID).Find(&topicPosts)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-08
      • 2017-04-23
      • 2021-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      相关资源
      最近更新 更多