如何使用Golang处理MongoDB文档数据并遍历expenses字段取值
操作MongoDB返回文档的两种实现方案
你可以根据业务场景选择以下任意一种方式读取、操作文档字段:
方案1:直接操作map[string]interface{}类型结果
如果你调用Decode时直接将返回结果解析成了map[string]interface{},可以通过逐层类型断言读取对应字段,示例代码如下:
// 假设res为FindOne返回后解码得到的map[string]interface{}变量 // 先读取expenses数组,断言为[]interface{}类型 expensesRaw, ok := res["expenses"].([]interface{}) if !ok { fmt.Println("expenses字段格式不匹配") return } // 遍历数组内所有消费项 for _, item := range expensesRaw { // 把每个消费项断言为map[string]interface{} expense, ok := item.(map[string]interface{}) if !ok { continue } // 分别读取分类和金额字段 category := expense["category"].(string) amount := expense["amount"].(float64) // 打印输出 fmt.Printf("消费分类:%s,消费金额:%.2f\n", category, amount) }
这种方案不需要提前定义结构体,适合临时查询、字段结构不固定的场景,缺点是需要做大量类型校验,容易引发panic。
方案2:结构体反序列化(生产环境更推荐)
提前和MongoDB文档结构对齐定义结构体,解码时直接将结果反序列化为结构体实例,后续操作和普通Go结构体完全一致,不需要额外类型断言:
import "go.mongodb.org/mongo-driver/bson/primitive" // 定义消费项结构体 type Expense struct { Category string `bson:"category"` Amount float64 `bson:"amount"` } // 定义完整文档结构体 type BillDoc struct { ID primitive.ObjectID `bson:"_id"` ChatID int `bson:"chatID"` Expenses []Expense `bson:"expenses"` Income []interface{} `bson:"income"` } // 调用FindOne后直接解码到结构体实例 var bill BillDoc err := collection.FindOne(context.TODO(), filter).Decode(&bill) if err != nil { log.Fatal("查询文档失败:", err) } // 直接遍历expenses字段即可 for _, exp := range bill.Expenses { fmt.Printf("消费分类:%s,消费金额:%.2f\n", exp.Category, exp.Amount) }
这种方案代码可读性、可维护性更高,出错概率更低,是正式项目的首选实现方式。
内容的提问来源于stack exchange,提问作者satad227
相关产品推荐
相关产品推荐

