英文:
Dynamic ConditionBuilder
问题
我的问题非常简单,我想动态创建过滤器并在查询输入中使用它。我必须明确指出,tf变量不能改变。
所以这是我做的:
totalFilter := expression.ConditionBuilder{}
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
tf := []expression.ConditionBuilder{filter, filter2, filter3}
for _, v := range tf {
totalFilter = totalFilter.And(v)
}
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
if err != nil {
log.Println(err)
return err
}
但问题是totalFilter是一个空结构体,所以它的mode变量等于0,然后引发警报,因为mode 0是unsetCond。
我找到的唯一解决方法是这样做:
for i, v := range tf {
if i == 0 {
totalFilter = v
} else {
totalFilter.And(v)
}
}
但我想知道是否还有其他解决方案。
英文:
My problem is pretty simple, I would like to dynamically create filters to use it in my query input.
I must precise that the tf variable can't change.
So here is what I did :
totalFilter := expression.ConditionBuilder{}
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
tf := []expression.ConditionBuilder{filter, filter2, filter3}
for _, v := range tf {
totalFilter = totalFilter.And(v)
}
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
if err != nil {
log.Println(err)
return err
}
But the probleme is that totalFilter is an empty struct so it's mode variable is equal to 0 and then it raise an alert because mode 0 is unsetCond.
The only workaround that I found is to do this :
for i, v := range tf {
if i == 0 {
totalFilter = v
} else {
totalFilter.And(v)
}
}
But I was wondering if there is another solution.
答案1
得分: 1
你可以通过创建一个自定义的可变参数函数来抽象化对第一个expression.ConditionBuilder
的处理,该函数至少需要一个expression.ConditionBuilder
参数:
func And(first expression.ConditionBuilder, rest ...expression.ConditionBuilder) expression.ConditionBuilder {
result := first
for _, cb := range rest {
result = result.And(cb)
}
return result
}
然后,在main
函数中使用:
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
totalFilter := And(filter, filter2, filter3)
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
// 其他操作...
请注意,expression
包中还导出了一个名为And
的类似函数,但它需要至少两个(而不仅仅是一个)expression.ConditionBuilder
参数。这有点不幸...
英文:
You could abstract away the treatment of the first expression.ConditionBuilder
in a custom variadic function taking at least one expression.ConditionBuilder
parameter:
func And(first expression.ConditionBuilder, rest ...expression.ConditionBuilder) expression.ConditionBuilder {
result := first
for _, cb := range rest {
result = result.And(cb)
}
return result
}
Then, in main
:
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
totalFilter := And(filter, filter2, filter3)
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
// etc.
Note that a similar function, also named And
, is exported by the expression
package, but it takes at least two (not just one) expression.ConditionBuilder
parameters. That's unfortunate...
答案2
得分: 0
我的方法是创建一个“虚拟”条件,它始终返回true,就像动态SQL语句中常见的WHERE 1=1 [AND ...]
条件一样。
示例代码将变为:
// 虚拟条件 (1=1) 用于初始化过滤器
totalFilter := expression.Equal(expression.Value(1), expression.Value(1))
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
tf := []expression.ConditionBuilder{filter, filter2, filter3}
for _, v := range tf {
totalFilter = totalFilter.And(v)
}
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
if err != nil {
log.Println(err)
return err
}
请注意,如果您的其他条件是通过“OR”操作连接的,则虚拟条件需要被反转,以便始终返回false。
英文:
My approach was to create a "dummy" condition that will always return true, much like the WHERE 1=1 [AND ...]
condition that is common in dynamic SQL statements.
The example code would become:
// dummy condition (1=1) to initialize the filter
totalFilter := expression.Equal(expression.Value(1), expression.Value(1))
filter := expression.Name("status").Equal(expression.Value("0"))
filter2 := expression.Name("foo").Equal(expression.Value("bar"))
filter3 := expression.Name("yes").Equal(expression.Value("no"))
tf := []expression.ConditionBuilder{filter, filter2, filter3}
for _, v := range tf {
totalFilter = totalFilter.And(v)
}
expr := expression.NewBuilder().WithFilter(totalFilter)
builder, err := expr.Build()
if err != nil {
log.Println(err)
return err
}
Note that if your other conditions are joined by an OR
operation, the dummy condition would need to be inverted so that it always returns false.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论