如何将Golang MongoDB动态字符串Filter转为find()可用的interface{}类型
在Golang中处理前端传入的动态MongoDB过滤器字符串
最优方案:改用JSON格式传递过滤器
前端直接传Go代码格式的字符串本身不符合前后端数据交换的常规逻辑,建议让前端传递JSON格式的过滤器,这样在Go中可以直接解析为MongoDB支持的bson.M或bson.D类型,简单可靠:
import ( "context" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" ) func main() { // 前端传入的JSON格式过滤器示例 filterJSON := `{"$and": [{"rating": {"$gt": 7}}, {"rating": {"$lte": 10}}]}` // 解析为bson.M(灵活的键值对结构) var filter bson.M err := bson.UnmarshalJSON([]byte(filterJSON), &filter) if err != nil { // 处理解析错误 panic(err) } // 或者解析为bson.D(有序键值对结构) // var filter bson.D // err := bson.UnmarshalJSON([]byte(filterJSON), &filter) // 传入Find方法使用 coll := getMongoCollection() // 假设这是你的集合实例 cursor, err := coll.Find(context.Background(), filter) if err != nil { panic(err) } }
若必须处理Go代码格式的字符串(不推荐)
Go没有运行时执行字符串代码的eval功能,无法直接把这段字符串转换成对应的bson.D实例。如果一定要处理这种格式,只能自己实现解析逻辑,或者利用Go的AST语法树包来解析代码结构并转换:
import ( "go/ast" "go/parser" "go/token" "strconv" "strings" "go.mongodb.org/mongo-driver/bson" ) // parseFilterString 解析Go代码格式的bson字符串为可用的过滤器 func parseFilterString(filterStr string) (interface{}, error) { fset := token.NewFileSet() expr, err := parser.ParseExpr(filterStr) if err != nil { return nil, err } return traverseASTNode(expr), nil } // traverseASTNode 递归遍历AST节点,转换为bson类型 func traverseASTNode(node ast.Node) interface{} { switch n := node.(type) { // 处理bson.D的结构体字面量,比如bson.D{{key, val}, ...} case *ast.StructLit: d := bson.D{} for _, elt := range n.Elts { kv := elt.(*ast.KeyValueExpr) key := kv.Key.(*ast.Ident).Name val := traverseASTNode(kv.Value) d = append(d, bson.E{Key: key, Value: val}) } return d // 处理bson.A的切片字面量,比如bson.A{val1, val2, ...} case *ast.CompositeLit: if selExpr, ok := n.Type.(*ast.SelectorExpr); ok && selExpr.Sel.Name == "A" { a := bson.A{} for _, elt := range n.Elts { a = append(a, traverseASTNode(elt)) } return a } // 处理基础字面量:字符串、数字等 case *ast.BasicLit: switch n.Kind { case token.INT: num, _ := strconv.Atoi(n.Value) return num case token.FLOAT: num, _ := strconv.ParseFloat(n.Value, 64) return num case token.STRING: return strings.Trim(n.Value, `"`) } } return nil }
注意:这种方式需要覆盖所有可能的bson类型和嵌套场景,实现成本高、容易出bug,强烈建议优先采用JSON格式的方案。
内容的提问来源于stack exchange,提问作者oakkose
相关产品推荐
相关产品推荐

