Scala中无法向MongoDB插入List[Map[String,String]]的问题
Scala中MongoDB $setOnInsert插入List[Map[String,String]]类型报错的解决方法
问题说明
使用Scala版MongoDB驱动执行updateOne upsert操作时,$setOnInsert子句中包含List[Map[String, String]]类型字段会触发「Cannot resolve overloaded method 'Document'」错误。插入String或List[String]类型时无异常。
报错代码
collection.updateOne( Filters.and(myFilters: _*), Document( "$setOnInsert" -> Document( "field" -> item.getAs[List[Map[String, String]]]("field") ) ), UpdateOptions().upsert(true) )
错误堆栈
overloaded method value apply with alternatives: (underlying: org.mongodb.scala.bson.BsonDocument)org.mongodb.scala.bson.collection.immutable.Document <and> (elems: org.mongodb.scala.bson.BsonMagnets.CanBeBsonElements)org.mongodb.scala.bson.collection.immutable.Document <and> (elems: org.mongodb.scala.bson.BsonMagnets.CanBeBsonElement*)org.mongodb.scala.bson.collection.immutable.Document <and> (json: String)org.mongodb.scala.bson.collection.immutable.Document cannot be applied to ((String, List[Map[String,String]])) "$setOnInsert" -> Document(
解决方法
问题核心是MongoDB Scala驱动无法自动将List[Map[String,String]]转换为兼容的Bson类型,需手动处理Map到Document的转换。
方法1:即时转换Map为Document
直接在赋值时将列表中的每个Map转为Document:
collection.updateOne( Filters.and(myFilters: _*), Document( "$setOnInsert" -> Document( "field" -> item.getAs[List[Map[String, String]]]("field").map(_.map(Document(_))) ) ), UpdateOptions().upsert(true) )
通过_.map(Document(_))将每个Map[String,String]转换为驱动可识别的Document实例。
方法2:定义全局隐式转换
如果需要频繁处理此类类型,添加全局隐式转换规则,让驱动自动完成转换:
import org.mongodb.scala.bson.collection.immutable.Document // 隐式转换:Map[String,String] -> Document implicit def mapToDoc(map: Map[String, String]): Document = Document(map) // 隐式转换:List[Map[String,String]] -> List[Document] implicit def listMapToListDoc(list: List[Map[String, String]]): List[Document] = list.map(mapToDoc)
添加后无需修改原业务代码,驱动会自动应用转换规则。
方法3:手动构建BsonArray
直接使用BsonArray明确构建Bson数组类型,适用于需要精确控制Bson结构的场景:
import org.mongodb.scala.bson.BsonArray collection.updateOne( Filters.and(myFilters: _*), Document( "$setOnInsert" -> Document( "field" -> item.getAs[List[Map[String, String]]]("field").map { list => BsonArray(list.map(Document(_))) } ) ), UpdateOptions().upsert(true) )
内容的提问来源于stack exchange,提问作者czr_RR
相关产品推荐
相关产品推荐

