获取嵌套对象的方法是使用一个查询。

huangapple go评论85阅读模式
英文:

Get nested object with one query

问题

我有以下模型:

type Instance struct {
    gorm.Model
    Name               string `gorm:"unique;"`
    UserID             uint
    GroupID            uint
    StackID            uint
    RequiredParameters []InstanceRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requiredParameters,omitempty"`
    OptionalParameters []InstanceOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"optionalParameters,omitempty"`
    DeployLog          string                      `gorm:"type:text"`
}

type InstanceRequiredParameter struct {
    gorm.Model
    InstanceID               uint                   `gorm:"index:idx_instance_required_parameter,unique"`
    StackRequiredParameterID uint                   `gorm:"index:idx_instance_required_parameter,unique"`
    StackRequiredParameter   StackRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
    Value                    string
}

type InstanceOptionalParameter struct {
    gorm.Model
    InstanceID               uint                   `gorm:"index:idx_instance_optional_parameter,unique"`
    StackOptionalParameterID uint                   `gorm:"index:idx_instance_optional_parameter,unique"`
    StackOptionalParameter   StackOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
    Value                    string
}

type StackRequiredParameter struct {
    gorm.Model
    StackID uint   `gorm:"index:idx_name_required_parameter,unique"`
    Name    string `gorm:"index:idx_name_required_parameter,unique"`
}

type StackOptionalParameter struct {
    gorm.Model
    StackID uint   `gorm:"index:idx_name_optional_parameter,unique"`
    Name    string `gorm:"index:idx_name_optional_parameter,unique"`
}

我正在尝试获取带有参数的实例,并且还需要检索StackRequiredParameter/StackOptionalParameter,因为我需要Name属性。

我可以使用以下函数来实现:

func (r instanceRepository) FindWithParametersById(id uint) (*model.Instance, error) {
    var instance *model.Instance
    err := r.db.First(&instance, id).Error
    if err != nil {
        return nil, err
    }

    var requiredParameters []model.InstanceRequiredParameter
    err = r.db.
        Where("instance_id = ?", id).
        Preload("StackRequiredParameter").
        Find(&requiredParameters).Error
    if err != nil {
        return nil, err
    }

    var optionalParameters []model.InstanceOptionalParameter
    err = r.db.
        Where("instance_id = ?", id).
        Preload("StackOptionalParameter").
        Find(&optionalParameters).Error
    if err != nil {
        return nil, err
    }

    instance.RequiredParameters = requiredParameters
    instance.OptionalParameters = optionalParameters

    return instance, nil
}

但这需要3个查询。有人可以建议使用Gorm只进行一次查询的方法吗?

英文:

I have the following model

type Instance struct {
	gorm.Model
	Name               string `gorm:"unique;"`
	UserID             uint
	GroupID            uint
	StackID            uint
	RequiredParameters []InstanceRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"requiredParameters,omitempty"`
	OptionalParameters []InstanceOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;" json:"optionalParameters,omitempty"`
	DeployLog          string                      `gorm:"type:text"`
}

type InstanceRequiredParameter struct {
	gorm.Model
	InstanceID               uint                   `gorm:"index:idx_instance_required_parameter,unique"`
	StackRequiredParameterID uint                   `gorm:"index:idx_instance_required_parameter,unique"`
	StackRequiredParameter   StackRequiredParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
	Value                    string
}

type InstanceOptionalParameter struct {
	gorm.Model
	InstanceID               uint                   `gorm:"index:idx_instance_optional_parameter,unique"`
	StackOptionalParameterID uint                   `gorm:"index:idx_instance_optional_parameter,unique"`
	StackOptionalParameter   StackOptionalParameter `gorm:"constraint:OnUpdate:CASCADE,OnDelete:CASCADE;"`
	Value                    string
}

type StackRequiredParameter struct {
	gorm.Model
	StackID uint   `gorm:"index:idx_name_required_parameter,unique"`
	Name    string `gorm:"index:idx_name_required_parameter,unique"`
}

type StackOptionalParameter struct {
	gorm.Model
	StackID uint   `gorm:"index:idx_name_optional_parameter,unique"`
	Name    string `gorm:"index:idx_name_optional_parameter,unique"`
}

I'm trying to get an instance with parameters and the StackRequiredParameter/StackOptionalParameter retrived as well since I need the Name property.

I can do it with the following function

func (r instanceRepository) FindWithParametersById(id uint) (*model.Instance, error) {
	var instance *model.Instance
	err := r.db.First(&instance, id).Error
	if err != nil {
		return nil, err
	}

	var requiredParameters []model.InstanceRequiredParameter
	err = r.db.
		Where("instance_id = ?", id).
		Preload("StackRequiredParameter").
		Find(&requiredParameters).Error
	if err != nil {
		return nil, err
	}

	var optionalParameters []model.InstanceOptionalParameter
	err = r.db.
		Where("instance_id = ?", id).
		Preload("StackOptionalParameter").
		Find(&optionalParameters).Error
	if err != nil {
		return nil, err
	}

	instance.RequiredParameters = requiredParameters
	instance.OptionalParameters = optionalParameters

	return instance, nil
}

But that takes 3 queries. Can anyone suggest a way to do it with just one query using Gorm?

答案1

得分: 0

你可以使用类似以下的代码来实现:

func (r instanceRepository) FindWithParametersById(id uint) (*model.Instance, error) {
    var instance *model.Instance
    err := r.db.Preload("RequiredParameters.StackRequiredParameter").Preload("OptionalParameters.StackOptionalParameter").First(&instance, id).Error
    if err != nil {
        return nil, err
    }

    return instance, nil
}

这段代码会在数据库中执行多个查询,因为每个Preload调用都会运行一个单独的查询,但至少你不必编写那么多代码了。

英文:

You should be able to do that with something like this:

func (r instanceRepository) FindWithParametersById(id uint) (*model.Instance, error) {
    var instance *model.Instance
    err := r.db.Preload("RequiredParameters.StackRequiredParameter").Preload("OptionalParameters.StackOptionalParameter").First(&instance, id).Error
    if err != nil {
        return nil, err
    }

    return instance, nil
}

It will still perform multiple queries in your database, because each Preload call runs a separate query, but at least you don't have to write all that code.

huangapple
  • 本文由 发表于 2021年6月9日 19:59:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/67903718.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定