如何使用Go语言mgo库通过单次调用向MongoDB插入文档数组?
解决mgo批量插入MongoDB文档的问题
嘿,这个问题我之前踩过坑!刚好知道怎么解决,给你详细说下~
首先,你遇到的报错根源是mgo的Insert方法参数用法不对。mgo的Collection.Insert签名是func (c *Collection) Insert(docs ...interface{}) error,它接收的是可变数量的单个文档参数,而不是直接接收一个切片。如果你直接把[]Transaction切片传进去,Go会把整个切片当成单个文档处理,MongoDB自然会报错,因为它没法把Go的切片直接映射成合法的BSON文档。
正确的做法:用...展开切片
你只需要在传入切片的时候加上...,把切片里的每个元素都作为独立的参数传给Insert,这样就和MongoDB的db.collection.insert()行为一致了——单次调用插入多个独立文档。
完整代码示例
- 先定义你的
Transaction结构体(记得加上正确的bson标签):
import ( "time" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) type Transaction struct { ID bson.ObjectId `bson:"_id,omitempty"` Amount float64 `bson:"amount"` Timestamp time.Time `bson:"timestamp"` // 这里根据你的需求添加其他字段 }
- 处理POST请求并批量插入的逻辑:
import ( "encoding/json" "fmt" "net/http" ) func saveTransactions(w http.ResponseWriter, r *http.Request) { // 解析POST请求体到Transaction切片 var transactions []Transaction err := json.NewDecoder(r.Body).Decode(&transactions) if err != nil { http.Error(w, "解析请求体失败: "+err.Error(), http.StatusBadRequest) return } defer r.Body.Close() // 连接MongoDB并获取集合 session, err := mgo.Dial("mongodb://localhost:27017") if err != nil { http.Error(w, "连接数据库失败: "+err.Error(), http.StatusInternalServerError) return } defer session.Close() // 确保会话关闭 session.SetMode(mgo.Monotonic, true) // 设置合适的会话模式 coll := session.DB("your_database_name").C("transactions") // 关键:用...展开切片,每个元素作为独立文档插入 err = coll.Insert(transactions...) if err != nil { http.Error(w, "批量插入失败: "+err.Error(), http.StatusInternalServerError) return } w.WriteHeader(http.StatusCreated) w.Write([]byte(fmt.Sprintf("成功插入%d条交易记录", len(transactions)))) }
额外注意事项
- bson标签一定要正确:如果你的结构体字段和MongoDB的字段名不一致,或者需要忽略某些字段,一定要通过
bson标签指定,否则mgo无法正确映射数据。 - 大切片分块处理:如果你的交易数组非常大(比如超过1万条,或者总大小接近MongoDB的单次请求上限16MB),建议把切片分成多个小批次插入,避免触发MongoDB的请求大小限制。
- 会话模式选择:根据你的业务场景选择合适的mgo会话模式(比如
Monotonic适合大多数读多写少的场景)。
内容的提问来源于stack exchange,提问作者Nidhin David
相关产品推荐
相关产品推荐

