如何将Mongo BasicDBList转换为不可变的Scala列表

7

我有一个已经持久化到数据库中的BasicDBList。现在我正在读取数据,尝试将此列表转换为不可变的Scala列表,方法如下:

val collection = mongoFactory.getCollection("tokens")    
val appId = MongoDBObject("appId" -> id)
val appDBObject = collection.findOne(appId) 
val scope: List[String] = appDBObject.get("scope").asInstanceOf[List[String]]

然而,我遇到了一个类强制转换异常,说无法将BasicDBList强制转换为Scala不可变列表。

我尝试了各种组合,例如转换为映射等,但似乎没有什么作用。

1个回答

13
因为MongoDB以与JavaScript相同的方式存储数组——作为一个带有整数键表示其索引的对象——所以BasicDBList在内部是必要的,以表示从线路上获取的对象。因此,目前Casbah不会自动将其表示为Scala列表...... BasicDBList是HashMap,而不是List。
然而,在内部,Casbah确实提供了隐式转换,让您将BasicDBList视为LinearSeq [AnyRef]; LinearSeq在类型树上与List有些不同,但出于各种原因更适合。不幸的是,您不能使用隐式转换进行强制转换。
现在,我建议您将项目作为DBList获取,然后将其类型注释为LinearSeq(这将使用隐式),或者仅对其调用toList(隐式将提供toList方法)。
scala> val l = MongoDBList("foo", "bar", "baz")
l: com.mongodb.BasicDBList = [ "foo" , "bar" , "baz"]

scala> val obj = MongoDBObject("list" -> l)
obj: com.mongodb.casbah.commons.Imports.DBObject = { "list" : [ "foo" , "bar" , "baz"]}

scala> obj.as[BasicDBList]("list")
res8: com.mongodb.casbah.Imports.BasicDBList = [ "foo" , "bar" , "baz"]

scala> obj.as[BasicDBList]("list").toList
res9: List[AnyRef] = List(foo, bar, baz)
as[T]: TgetAs[T]: Option[T]方法比强制类型转换更好,因为它们内部有一些技巧来进行类型转换。顺便说一下,Casbah的下一个版本将包括代码,如果您请求Seq、List等并且它是DBList,则asgetAs自动将它们转换为您请求的类型。请注意保留HTML标签。

7
@venividivamos list collect { case s: String => s } 将从 List[AnyRef] 中获取所有的 String,并返回一个包含它们的 List[String] - Daniel C. Sobral
1
是的,@DCSobrals 的答案是最佳选择。因为在MongoDB中你无法“输入” 集合,所以除非遍历集合否则无法保证内容是特定类型。收集它们会更安全。实际上,我将在下一个版本中借鉴这种方法,试图将整个集合强制转换为给定类型。 - Brendan W. McAdams
3
截至2.1.5.0,这个还有效吗?我收到了一个编译错误,提示“值toList不是com.mongodb.BasicDBList的成员”。 - Ben Dilts
@DanielC.Sobral 如果数组包含一个元组,例如 Array[(String, Double)] 或者相同的 Map,它该如何工作呢? - andyczerwonka
旁边的问题 - 你会如何将MongoDBList转换为可以传递到collection.find(...)collection.insert(...)MongoDBObject - Kevin Meredith
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接