#scala #mongodb #casbah
#scala #mongodb #касба
Вопрос:
У меня есть базовый список, который был сохранен в базе данных. Сейчас я считываю данные и пытаюсь преобразовать список в неизменяемый список 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]]
Однако я получаю исключение приведения класса, в котором говорится, что невозможно преобразовать базовый список в неизменяемый список Scala.
Я пробовал различные комбинации, такие как преобразование в карту и т.д. Кажется, ничего не работает.
Ответ №1:
Поскольку MongoDB хранит массивы так же, как это делает JavaScript — в виде объекта с целочисленными ключами, указывающими их индекс, — BasicDBList необходим внутренне для представления объекта, выходящего из сети. Таким образом, в настоящее время Casbah не представляет его автоматически как список Scala…. BasicDBList — это хэш-карта, а не список.
ОДНАКО внутренне 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
автоматически преобразует их в запрошенный вами тип.
Комментарии:
1. Спасибо за этот ответ. Я тоже пробовал этот подход. Но я не смог выяснить, как преобразовать List[AnyRef] в List[String], поскольку я хочу результат в виде списка строк. Может быть просто, но не уверен, как это сделать.
2. @venividivamos
list collect { case s: String => s }
извлечет всеString
из aList[AnyRef]
и вернетList[String]
с ними.3. Да, ответ @DCSobrals — лучший выбор. Поскольку вы не можете «вводить» коллекции в MongoDB, нет способа гарантировать, что содержимое относится к определенному типу, за исключением обхода коллекции. Собирать их было бы безопаснее. Фактически, я собираюсь использовать этот подход для следующего выпуска, чтобы «попытаться» привести всю коллекцию к заданному типу.
4. @Daniel Именно то, что я хотел. Большое спасибо.
5. Это все еще актуально с версии 2.1.5.0? Я получаю ошибку компиляции о том, что «значение ToList не является членом com.mongodb.BasicDBList»