首页 > 解决方案 > 一次查询获取嵌套对象

问题描述

我有以下型号

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"`
}

我正在尝试获取一个带有参数的实例,并且由于我需要 Name 属性,因此也检索了 ​​StackRequiredParameter/StackOptionalParameter。

我可以用以下功能做到这一点

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 进行一次查询吗?

标签: gogo-gorm

解决方案


您应该可以通过以下方式做到这一点:

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调用都运行一个单独的查询,但至少您不必编写所有代码。


推荐阅读