使用Web请求Query参数构造MongoDB Go Driver过滤条件返回null,求差异
Query参数构造MongoDB查询返回空,手动构造却有效?
我尝试通过Web请求的Query参数查询MongoDB,已经成功解析参数并添加到bson.D中,但查询始终返回空结果。相关代码如下:
router.HandleFunc("/route", func(w http.ResponseWriter, r *http.Request) { coll := s.MongoDB.Database("the-database").Collection("collection") filter := bson.D{} for key, value := range r.URL.Query() { for _, value := range value { filter = append(filter, bson.E{key, value}) fmt.Println("filter: ", reflect.TypeOf(value)) } } cursor, err := coll.Find(context.TODO(), filter1) if err != nil { w.Write([]byte("Unable find any items.")) } var items []Property if err = cursor.All(context.TODO(), &items); err != nil { w.Write([]byte("Unable find any items.")) } jsonData, err := json.MarshalIndent(items, "", " ") if err != nil { panic(err) } w.Write([]byte(jsonData)) })
但手动向bson.D中添加bson.E却能成功返回结果:
filter1 := bson.D{} filter1 = append(filter1, bson.E{"key", 1234})
即使打印两个filter的结果看起来完全一致,用reflect.DeepEqual比较却返回false:
// curl "http://localhost:8080/api/v1/route?key=1234" filter: [{key 1234}] TypeOf: primitive.E // reflect.TypeOf(filter[0]) // filter1 := bson.D{}; filter1 = append(filter1, bson.E{"key", 1234}) filter1: [{key 1234}] TypeOf: primitive.E // reflect.TypeOf(filter1[0]) fmt.Print(reflect.DeepEqual(filter, filter1)) // False
想知道这两个filter的差异是什么,为何一个有效一个无效?
核心差异:参数值的类型不同
输出看起来一致,但Query参数解析出的value是字符串类型,而手动构造的1234是整数类型。MongoDB是强类型数据库,查询时会严格匹配字段值的类型:
- 从Query参数拿到的
"1234"是string,构造的filter实际是bson.E{Key: "key", Value: "1234"} - 手动构造的是
bson.E{Key: "key", Value: 1234},这里的1234是int类型
这就是reflect.DeepEqual返回false的原因——两个值的底层类型完全不同,若数据库中key字段是整数类型,自然查不到匹配的文档。
解决方案:转换Query参数的类型
需要根据数据库中字段的实际类型,将Query参数的字符串值转换为对应类型,比如整数:
import "strconv" // ... filter := bson.D{} for key, values := range r.URL.Query() { for _, valStr := range values { // 假设key对应的字段是int类型,尝试转换字符串为整数 valInt, err := strconv.Atoi(valStr) if err != nil { // 处理转换失败的情况,比如返回错误响应 w.WriteHeader(http.StatusBadRequest) w.Write([]byte(fmt.Sprintf("Invalid value for %s: must be integer", key))) return } filter = append(filter, bson.E{Key: key, Value: valInt}) } } // 注意修正原代码的笔误:使用构造好的filter查询 cursor, err := coll.Find(context.TODO(), filter)
如果涉及多种类型(如字符串、浮点数、布尔值),可以根据字段名做针对性的类型转换,或者使用bson.M配合类型断言来灵活处理。
另外注意原代码中的笔误:coll.Find(context.TODO(), filter1)应该改为coll.Find(context.TODO(), filter),否则会始终使用手动构造的filter1查询,这也是可能导致问题的关键点。
内容的提问来源于stack exchange,提问作者itsOnly1_Jah
相关产品推荐
相关产品推荐

