как преобразовать Mongo BasicDBList в неизменяемый список scala

У меня есть 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.

Я пробовал различные комбинации, такие как преобразование в карту и т. д. Кажется, ничего не работает.


person gofeddy    schedule 25.04.2011    source источник


Ответы (1)


Поскольку MongoDB хранит массивы так же, как JavaScript — как объект с целочисленными ключами, указывающими их индекс, — BasicDBList необходим для внутреннего представления объекта, исходящего из сети. Таким образом, в настоящее время Casbah не представляет его автоматически как список Scala... BasicDBList - это HashMap, а не список.

ОДНАКО, внутренне 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]: T и getAs[T]: Option[T] предпочтительнее приведения, так как они содержат некоторые хитрости для массажа типов. Следующий выпуск Casbah будет включать код, так что если вы запросите Seq, List и т. д., а это DBList, as и getAs будут автоматически преобразовывать их в требуемый тип.

person Brendan W. McAdams    schedule 25.04.2011
comment
Спасибо за этот ответ. Я тоже пробовал этот подход. Но я не смог понять, как преобразовать List[AnyRef] в List[String], так как мне нужен результат в виде списка строк. Может быть просто, но не уверен, как. - person gofeddy; 25.04.2011
comment
@venividivamos list collect { case s: String => s } получит все String из List[AnyRef] и вернет с ними List[String]. - person Daniel C. Sobral; 25.04.2011
comment
Да, ответ @DCSobrals о лучшем варианте. Поскольку вы не можете вводить коллекции в MongoDB, нет способа гарантировать, что содержимое коллекции относится к определенному типу, кроме обхода коллекции. Собрать их было бы безопаснее. На самом деле, я собираюсь украсть этот подход для следующего выпуска, чтобы «попытаться» привести всю коллекцию к заданному типу. - person Brendan W. McAdams; 25.04.2011
comment
@ Даниэль Именно то, что я хотел. Большое спасибо. - person gofeddy; 25.04.2011
comment
Это все еще действует с 2.1.5.0? Я получаю сообщение об ошибке компиляции, что значение toList не является членом com.mongodb.BasicDBList - person Ben Dilts; 12.06.2012
comment
@DanielC.Sobral, как это будет работать, если массив содержит кортеж, например Массив [(String, Double)] или карта того же? - person andyczerwonka; 29.09.2013
comment
@andyczerwonka list collect { case arr: Array[_] => arr collect { case (s: String, d: Double) => (s, d) } } или что-то в этом роде. - person Daniel C. Sobral; 30.09.2013
comment
Дополнительный вопрос: как бы вы преобразовали MongoDBList в MongoDBObject, который можно было бы передать в collection.find(...) или collection.insert(...)? - person Kevin Meredith; 15.10.2013
comment
@DanielC.Sobral Спасибо, что упомянули collect. Заставил меня понять, что даже map выполняет частичные функции. - person akauppi; 18.11.2014