一次查询获取嵌套对象

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,因为我需要名称 属性。

我可以用下面的函数来做

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 仅通过一个查询来完成此操作的方法吗?

你应该可以用这样的东西来做到这一点:

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