补充标签过滤 LIKE模式
This commit is contained in:
parent
13ea1f2e04
commit
1b27d97f2a
@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/label"
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/label"
|
||||||
|
"github.com/infraboard/mcube/v2/exception"
|
||||||
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
"github.com/infraboard/mcube/v2/ioc/config/datasource"
|
||||||
"github.com/infraboard/mcube/v2/types"
|
"github.com/infraboard/mcube/v2/types"
|
||||||
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateLabel implements label.Service.
|
// CreateLabel implements label.Service.
|
||||||
@ -46,13 +48,23 @@ func (i *LabelServiceImpl) QueryLabel(ctx context.Context, in *label.QueryLabelR
|
|||||||
return set, nil
|
return set, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteLabel implements label.Service.
|
|
||||||
func (i *LabelServiceImpl) DeleteLabel(ctx context.Context, in *label.DeleteLabelRequest) (*label.Label, error) {
|
|
||||||
panic("unimplemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
// DescribeLabel implements label.Service.
|
// DescribeLabel implements label.Service.
|
||||||
func (i *LabelServiceImpl) DescribeLabel(ctx context.Context, in *label.DescribeLabelRequest) (*label.Label, error) {
|
func (i *LabelServiceImpl) DescribeLabel(ctx context.Context, in *label.DescribeLabelRequest) (*label.Label, error) {
|
||||||
|
query := datasource.DBFromCtx(ctx)
|
||||||
|
|
||||||
|
ins := &label.Label{}
|
||||||
|
if err := query.Where("id = ?", in.Id).First(ins).Error; err != nil {
|
||||||
|
if err == gorm.ErrRecordNotFound {
|
||||||
|
return nil, exception.NewNotFound("label %s not found", in.Id)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return ins, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteLabel implements label.Service.
|
||||||
|
func (i *LabelServiceImpl) DeleteLabel(ctx context.Context, in *label.DeleteLabelRequest) (*label.Label, error) {
|
||||||
panic("unimplemented")
|
panic("unimplemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,12 +8,16 @@ import (
|
|||||||
|
|
||||||
func TestCreateLabel(t *testing.T) {
|
func TestCreateLabel(t *testing.T) {
|
||||||
req := label.NewCreateLabelRequest()
|
req := label.NewCreateLabelRequest()
|
||||||
req.Key = "tech"
|
req.Key = "team"
|
||||||
req.KeyDesc = "技术部"
|
req.KeyDesc = "小组"
|
||||||
req.ValueType = label.VALUE_TYPE_ENUM
|
req.ValueType = label.VALUE_TYPE_ENUM
|
||||||
req.AddEnumOption(&label.EnumOption{
|
req.AddEnumOption(&label.EnumOption{
|
||||||
Label: "开发一组",
|
Label: "开发一组",
|
||||||
Value: "dev01",
|
Value: "dev01",
|
||||||
|
Children: []*label.EnumOption{
|
||||||
|
{Label: "后端开发", Value: "dev01.backend_developer"},
|
||||||
|
{Label: "前端开发", Value: "dev01.web_developer"},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
ins, err := svc.CreateLabel(ctx, req)
|
ins, err := svc.CreateLabel(ctx, req)
|
||||||
@ -22,3 +26,12 @@ func TestCreateLabel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
t.Log(ins)
|
t.Log(ins)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestQueryLabel(t *testing.T) {
|
||||||
|
req := label.NewQueryLabelRequest()
|
||||||
|
set, err := svc.QueryLabel(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
t.Log(set)
|
||||||
|
}
|
||||||
|
@ -11,8 +11,8 @@ func NewLabel(spc *CreateLabelRequest) (*Label, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &Label{
|
return &Label{
|
||||||
ResourceMeta: *apps.NewResourceMeta(),
|
ResourceMeta: *apps.NewResourceMeta(),
|
||||||
Spec: spc,
|
CreateLabelRequest: *spc,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ type Label struct {
|
|||||||
// 基础数据
|
// 基础数据
|
||||||
apps.ResourceMeta
|
apps.ResourceMeta
|
||||||
// 空间定义
|
// 空间定义
|
||||||
Spec *CreateLabelRequest `json:"spec" bson:",inline" gorm:"embedded"`
|
CreateLabelRequest `bson:",inline" gorm:"embedded"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *Label) TableName() string {
|
func (l *Label) TableName() string {
|
||||||
@ -65,13 +65,14 @@ type CreateCreateLabelSpec struct {
|
|||||||
// 适用于那些资源
|
// 适用于那些资源
|
||||||
Resources []string `json:"resources" bson:"resources" gorm:"column:resources;type:json;serializer:json;" description:"适用于那些资源" optional:"true"`
|
Resources []string `json:"resources" bson:"resources" gorm:"column:resources;type:json;serializer:json;" description:"适用于那些资源" optional:"true"`
|
||||||
|
|
||||||
// 标签的键, 标签的Key不允许修改, 带前缀的 tech.dev.frontend01 tech.dev.backend01
|
// 标签的键, 标签的Key不允许修改
|
||||||
Key string `json:"key" bson:"key" gorm:"column:key;type:varchar(255)" validate:"required"`
|
Key string `json:"key" bson:"key" gorm:"column:key;type:varchar(255)" validate:"required"`
|
||||||
// 标签的键的描述
|
// 标签的键的描述
|
||||||
KeyDesc string `json:"key_desc" bson:"key_desc" gorm:"column:key_desc;type:varchar(255)" validate:"required"`
|
KeyDesc string `json:"key_desc" bson:"key_desc" gorm:"column:key_desc;type:varchar(255)" validate:"required"`
|
||||||
// 标签的颜色
|
// 标签的颜色
|
||||||
Color string `json:"color" bson:"color" gorm:"column:color;type:varchar(100)"`
|
Color string `json:"color" bson:"color" gorm:"column:color;type:varchar(100)"`
|
||||||
|
|
||||||
|
// 标签的值相关信息, tech.dev.frontend01 tech.dev.backend01
|
||||||
// 值类型
|
// 值类型
|
||||||
ValueType VALUE_TYPE `json:"value_type" gorm:"column:value_type;type:varchar(20)" bson:"value_type"`
|
ValueType VALUE_TYPE `json:"value_type" gorm:"column:value_type;type:varchar(20)" bson:"value_type"`
|
||||||
// 标签默认值
|
// 标签默认值
|
||||||
@ -83,7 +84,7 @@ type CreateCreateLabelSpec struct {
|
|||||||
// 枚举值的选项
|
// 枚举值的选项
|
||||||
EnumOptions []*EnumOption `json:"enum_options,omitempty" bson:"enum_options" gorm:"column:enum_options;type:json;serializer:json;"`
|
EnumOptions []*EnumOption `json:"enum_options,omitempty" bson:"enum_options" gorm:"column:enum_options;type:json;serializer:json;"`
|
||||||
// 基于Http枚举的配置
|
// 基于Http枚举的配置
|
||||||
HttpEnumConfig HttpEnumConfig `json:"http_enum_config,omitempty" gorm:"embedded" bson:"http_enum_config"`
|
HttpEnumConfig HttpEnumConfig `json:"http_enum_config" gorm:"embedded" bson:"http_enum_config"`
|
||||||
// 值的样例
|
// 值的样例
|
||||||
Example string `json:"example" bson:"example" gorm:"column:example;type:text"`
|
Example string `json:"example" bson:"example" gorm:"column:example;type:text"`
|
||||||
|
|
||||||
@ -98,6 +99,8 @@ type EnumOption struct {
|
|||||||
Input string `json:"input" bson:"input" validate:"required"`
|
Input string `json:"input" bson:"input" validate:"required"`
|
||||||
// 选项的值, 根据parent.input + children.input 自动生成
|
// 选项的值, 根据parent.input + children.input 自动生成
|
||||||
Value string `json:"value" bson:"value"`
|
Value string `json:"value" bson:"value"`
|
||||||
|
// 是否禁止选中, 和前端UI组件配合使用
|
||||||
|
Disabled bool `json:"disabled" bson:"disabled"`
|
||||||
// 标签的颜色
|
// 标签的颜色
|
||||||
Color string `json:"color" bson:"color"`
|
Color string `json:"color" bson:"color"`
|
||||||
// 是否废弃
|
// 是否废弃
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package policy
|
package policy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/namespace"
|
"122.51.31.227/go-course/go18/devcloud/mcenter/apps/namespace"
|
||||||
@ -104,8 +105,18 @@ func (r ResourceScope) GormResourceFilter(query *gorm.DB) *gorm.DB {
|
|||||||
// 构建"标签值匹配"条件
|
// 构建"标签值匹配"条件
|
||||||
var valueMatches []clause.Expression
|
var valueMatches []clause.Expression
|
||||||
for _, val := range values {
|
for _, val := range values {
|
||||||
valueMatches = append(valueMatches,
|
if strings.Contains(val, "%") {
|
||||||
datatypes.JSONQuery("label").Equals(val, key))
|
// 如果值包含通配符%,使用LIKE条件
|
||||||
|
valueMatches = append(valueMatches,
|
||||||
|
clause.Expr{
|
||||||
|
SQL: "JSON_UNQUOTE(JSON_EXTRACT(label, ?)) LIKE ?",
|
||||||
|
Vars: []any{"$." + key, val},
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// 否则使用精确匹配
|
||||||
|
valueMatches = append(valueMatches,
|
||||||
|
datatypes.JSONQuery("label").Equals(val, key))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 组合条件:标签不存在 OR 标签值匹配
|
// 组合条件:标签不存在 OR 标签值匹配
|
||||||
|
@ -14,7 +14,7 @@ func TestCreateApplication(t *testing.T) {
|
|||||||
req.CodeRepository = application.CodeRepository{
|
req.CodeRepository = application.CodeRepository{
|
||||||
SshUrl: "git@122.51.31.227:go-course/go18.git",
|
SshUrl: "git@122.51.31.227:go-course/go18.git",
|
||||||
}
|
}
|
||||||
req.SetLabel("team", "golang_dev_group_01")
|
req.SetLabel("team", "dev01.web_developer")
|
||||||
ins, err := svc.CreateApplication(ctx, req)
|
ins, err := svc.CreateApplication(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -25,7 +25,8 @@ func TestCreateApplication(t *testing.T) {
|
|||||||
// SELECT * FROM `applications` WHERE (NOT JSON_EXTRACT(`label`,'$.team') IS NOT NULL OR JSON_EXTRACT(`label`,'$.team') = 'golang_dev_group_01') ORDER BY created_at desc LIMIT 20
|
// SELECT * FROM `applications` WHERE (NOT JSON_EXTRACT(`label`,'$.team') IS NOT NULL OR JSON_EXTRACT(`label`,'$.team') = 'golang_dev_group_01') ORDER BY created_at desc LIMIT 20
|
||||||
func TestQueryApplication(t *testing.T) {
|
func TestQueryApplication(t *testing.T) {
|
||||||
req := application.NewQueryApplicationRequest()
|
req := application.NewQueryApplicationRequest()
|
||||||
req.SetScope("team", []string{"golang_dev_group_01"})
|
// dev01.%
|
||||||
|
req.SetScope("team", []string{"%"})
|
||||||
// req.SetScope("env", []string{"prod"})
|
// req.SetScope("env", []string{"prod"})
|
||||||
ins, err := svc.QueryApplication(ctx, req)
|
ins, err := svc.QueryApplication(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user