MongoDB带ArrayFilters的updateMany转Golang代码报错求助
解决Go中MongoDB updateMany带ArrayFilters的bson错误
问题背景
原MongoDB查询:
db.batches.updateMany( {"batchedOrders.newOrderObject.orderDetails.trackingId" : "ORDER_JEET_2023_02_05_01"}, { $set: { "batchedOrders.$[elem].newOrderObject.pickupDetails.note" : "Welcome" } }, { arrayFilters: [ { "elem.newOrderObject.orderDetails.trackingId": "ORDER_JEET_2023_02_05_01" } ] } )
待更新的多字段数据存储在interface{}类型变量b中,结构如下:
{ "batchedOrders.$[elem].newOrderObject.dropoffDetails.recipientDetails.email": "das@rara.delivery", "batchedOrders.$[elem].newOrderObject.orderDetails.dimensions.height": 0, "batchedOrders.$[elem].newOrderObject.orderDetails.dimensions.length": 0, "batchedOrders.$[elem].newOrderObject.orderDetails.dimensions.unit": "cm", "batchedOrders.$[elem].newOrderObject.orderDetails.dimensions.width": 0, "batchedOrders.$[elem].newOrderObject.orderDetails.orderDeliveryDetails.sla.dropoff": 1675712794, "batchedOrders.$[elem].newOrderObject.orderDetails.parcelSize": "Medium", "batchedOrders.$[elem].newOrderObject.orderDetails.weightDetails.billableWeight": 5, "batchedOrders.$[elem].newOrderObject.orderDetails.weightDetails.volWeight": 5, "batchedOrders.$[elem].newOrderObject.orderDetails.weightDetails.weight": 5, "batchedOrders.$[elem].newOrderObject.orderDetails.weightIndex": 1, "batchedOrders.$[elem].newOrderObject.pickupDetails.pickupIncharge.name": "Mukesh" }
原Go代码运行时触发错误:
WriteString can only write while positioned on a Element or Value but is positioned on a TopLevel
错误原因
- bson结构不匹配:你对
interface{}类型的b执行了多余的bson.Marshal+Unmarshal操作,若doc定义为bson.D类型,会导致带点路径的键无法被正确解析——bson.D要求每个键是一级字段,而你用的是MongoDB嵌套路径表达式,两者结构不兼容。 - ArrayFilters的写法虽语法合法,但
bson.M比bson.D更适合存储路径表达式类型的过滤条件,可读性和容错性更强。
解决方案
修正后的代码
// 直接将interface{}类型的b断言为bson.M,避免不必要的bson转换 updateDoc, ok := b.(bson.M) if !ok { log.Println("invalid data type for update document") return false, errors.New("invalid update data") } // 用bson.M定义ArrayFilters,结构更直观 arrayFilters := options.ArrayFilters{ Filters: []interface{}{ bson.M{"elem.newOrderObject.orderDetails.trackingId": trackingId}, }, } opts := options.UpdateOptions{ ArrayFilters: &arrayFilters, } // 过滤条件用bson.M更清晰,也可保留bson.D写法 filter := bson.M{ "batchedOrders.newOrderObject.orderDetails.trackingId": trackingId, } res, err := db.Collection(BATCH_COLLECTION_NAME).UpdateMany( ctx, filter, bson.M{"$set": updateDoc}, &opts, ) if err != nil { log.Println(err) return false, err }
额外说明
- 如果
b是JSON字符串而非map类型,需先解析为bson.M:var updateDoc bson.M err := bson.UnmarshalJSON([]byte(jsonStr), &updateDoc) if err != nil { return false, err } - 避免用
bson.D存储带点路径的键值对,这类MongoDB路径表达式更适合用bson.M(无序map)来承载。
内容的提问来源于stack exchange,提问作者Mukesh Kumar Das
相关产品推荐
相关产品推荐

