Golang中MongoDB复合集合按Patient.Name过滤无结果问题排查
问题:MongoDB按患者姓名查询返回空结果的排查与修复
我想通过API请求体传入的Name字段,查询MongoDB中consentforms集合的匹配数据,但编写的Find过滤条件返回空结果(响应体显示null,无报错)。以下是我的Controller和Model代码,怀疑过滤逻辑或代码存在问题。
Controller代码
func GET_FormByPatientFullName(ctx *gin.Context) { col := mongodb.CLIENT.Database(config.DATABASE_NAME).Collection("consentforms") filter := bson.M{"Patient": bson.M{"Name": ctx.Query("name")}} cursor, err := col.Find(_CONTEXT.TODO(), filter) if err != nil { log.Fatal(err) } var results []general_models.ConsentForm if err = cursor.All(_CONTEXT.TODO(), &results); err != nil { log.Fatal(err) } for _, result := range results { res, _ := json.Marshal(result) fmt.Println(string(res)) } ctx.IndentedJSON(http.StatusOK, gin.H{"data": results}) }
Model代码
type ConsentForm struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` FormFileURL string `json:"FormFileURL" bson:"FormFileURL"` ProcessName string `json:"ProcessName" bson:"ProcessName"` DateOfNotification string `json:"DateOfNotification" bson:"DateOfNotification"` WitnessName string `json:"WitnessName" bson:"WitnessName"` WitnessSurname string `json:"WitnessSurname" bson:"WitnessSurname"` ResponsibleDoctor string `json:"ResponsibleDoctor" bson:"ResponsibleDoctor"` Patient IPatient `json:"Patient" bson:"Patient"` QuestionOptions IQuestionOptions `json:"QuestionOptions" bson:"QuestionOptions"` AdditionalDetails string `json:"AdditionalDetails" bson:"AdditionalDetails"` } type IPatient struct { // ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` Name string `json:"Name" bson:"Name"` Surname string `json:"Surname" bson:"Surname"` Birthdate string `json:"Birthdate" bson:"Birthdate"` TCKN string `json:"TCKN" bson:"TCKN"` FacePhotoURL string `json:"FacePhotoURL" bson:"FacePhotoURL"` SignatureImageURL string `json:"SignatureImageURL" bson:"SignatureImageURL"` }
排查与修复方案
1. 过滤条件写法错误
你当前的过滤条件bson.M{"Patient": bson.M{"Name": ...}}是在匹配整个Patient子文档完全等于{"Name": 传入值},而不是匹配Patient子文档中的Name字段。正确写法要使用MongoDB的点表示法,直接指定嵌套字段路径:
filter := bson.M{"Patient.Name": nameValue}
2. 请求参数获取方式错误
你明确说明要通过请求体传Name字段,但代码里用了ctx.Query("name")(从URL查询参数取值,比如?name=张三)。如果前端用POST请求的JSON体传参,需要先定义接收结构体,再绑定请求体:
type NameRequest struct { Name string `json:"name"` } var req NameRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求参数"}) return }
3. 错误处理不当
log.Fatal(err)会直接终止整个程序,这在API服务中是致命的,应该改为返回HTTP错误响应给客户端,而不是崩溃服务:
if err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return }
4. 字段大小写匹配问题
MongoDB字段名区分大小写,要确保数据库中consentforms集合的嵌套字段确实是Patient.Name(和你的bson标签一致),而非小写的patient.name或其他变体。
修正后的完整Controller代码
func GET_FormByPatientFullName(ctx *gin.Context) { // 定义请求体接收结构体 type NameRequest struct { Name string `json:"name"` } var req NameRequest if err := ctx.ShouldBindJSON(&req); err != nil { ctx.JSON(http.StatusBadRequest, gin.H{"error": "无效的请求参数"}) return } col := mongodb.CLIENT.Database(config.DATABASE_NAME).Collection("consentforms") // 正确的嵌套字段过滤条件 filter := bson.M{"Patient.Name": req.Name} cursor, err := col.Find(_CONTEXT.TODO(), filter) if err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } defer cursor.Close(_CONTEXT.TODO()) // 记得关闭游标释放资源 var results []general_models.ConsentForm if err = cursor.All(_CONTEXT.TODO(), &results); err != nil { ctx.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } ctx.IndentedJSON(http.StatusOK, gin.H{"data": results}) }
内容的提问来源于stack exchange,提问作者Poyraz HANCILAR
相关产品推荐
相关产品推荐

