'GORM select certain column with preload

Let's say I have these struct that represent my models

type QuestionHeader struct {
  QuestionHeaderId int    `gorm:"primaryKey;column:question_id" json:"question_id"`
  LevelId          int    `gorm:"column:level_id" json:"level_id"`
  SubjectId        int    `gorm:"column:subject_id" json:"subject_id"`
  QuestionBody     []QuestionBody
  QuestionSolution []QuestionSolution
  OtherColumn1A    string
  OtherColumn2A    string
}


type QuestionBody struct {
  QuestionBody  int    `gorm:"primaryKey;column:question_id" json:"question_id"`
  Value         string `gorm:"column:value" json:"value"`
  Type          string `gorm:"column:type" json:"type"`
  OtherColumn1B string
  OtherColumn2B string
}

type QuestionSolution struct {
  QuestionSolutionId int    `gorm:"primaryKey;column:question_id" json:"question_id"`
  Value              string `gorm:"column:value" json:"value"`
  Type               string `gorm:"column:type" json:"type"`
  OtherColumn1C      string
  OtherColumn2c      string
}

Then I want to do a query with preload like this

qs.db().
  Preload("QuestionHeader.QuestionBody", func(db *gorm.DB) *gorm.DB {
      return db.Where("question_body.status = ?", 1) 
       // I only want to select certain column here
  }).
  Preload("QuestionHeader.QuestionSolution", func(db *gorm.DB) *gorm.DB {
      return db.Where("question_solution.status = ?", 1) 
       // I only want to select certain column here
  }).
  Where("level_id = ?", 2).
  Find(&questionHeaders)  // I only want to select certain column here

But the catch with that code is, I will select all the columns based on my model property

What if I want to select only a certain column with preload? For example, I want to select only type for QuestionBody

I know that you can create another struct for your select statement as described in the docs, but are there any other ways? I don't want to create a struct for every select statement

In Laravel Eloquent, you can do something like this



Solution 1:[1]

There are few issue that i would like to point out

  • You don't have the many2many association defined in QuestionHeader for QuestionBody or QuestionSolution
  • In query you are using status column but I don't seem them defined in QuestionBody or QuestionSolution
  • Rename QuestionBody id column to QuestionBodyId in QuestionBody

As per the points changes would be as below:

type QuestionHeader struct {
  QuestionHeaderId int                `gorm:"primaryKey;column:question_id" json:"question_id"`
  LevelId          int                `gorm:"column:level_id" json:"level_id"`
  SubjectId        int                `gorm:"column:subject_id" json:"subject_id"`
  QuestionBody     []QuestionBody     `gorm:"many2many:question_header_question_bodies;"`
  QuestionSolution []QuestionSolution `gorm:"many2many:question_header_question_solutions;"`
  OtherColumn1A    string
  OtherColumn2A    string
}

type QuestionBody struct {
  QuestionBodyId  int   `gorm:"primaryKey;column:question_id" json:"question_id"`
  Value         string  `gorm:"column:value" json:"value"`
  Type          string  `gorm:"column:type" json:"type"`
  Status        uint8   `gorm:"column:status;default:0" json:"status"`
  OtherColumn1B string
  OtherColumn2B string
}

type QuestionSolution struct {
  QuestionSolutionId int    `gorm:"primaryKey;column:question_id" json:"question_id"`
  Value              string `gorm:"column:value" json:"value"`
  Type               string `gorm:"column:type" json:"type"`
  Status             uint8  `gorm:"column:status;default:0" json:"status"`
  OtherColumn1C      string
  OtherColumn2c      string
}
var questionHeaders QuestionHeader
db.
  Preload("QuestionBody", func(db *gorm.DB) *gorm.DB {
    return db.Where("Status = ?", 1).Select("QuestionBodyId", "Value")
  }).
  Preload("QuestionSolution", func(db *gorm.DB) *gorm.DB {
    return db.Where("Status = ?", 1).Select("QuestionSolutionId", "Value")
  }).
  Where("level_id = ?", 2).
  Select("SubjectId").
  Find(&questionHeaders)
}

In Preload Select we would have to include the unique primary key for gorm to uniquely identify the associated slice of structs

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Chandan