3

I have a document in MongoDB that looks like this:

{"_id":"asdf", "data":[
    {"a":"1","b":"2"}, 
    {"a":"3","b":"4"}, 
    {"a":"5","b":"6"}, 
]}

I would like to query that object using Scala, and convert the entries in "data" into a list of case classes. After a few hours' work, I've yet to come up with something that even compiles. Can someone point me to a tutorial with this information? This tutorial hasn't been any help. I've tried every combination of nested maps, fors, foreaches, casts, and pattern matching that I can come up with.

Edit: My super-ugly but now seemingly working code is now this:

def getData(source_id:String) = {
    val source = collection.findOne(MongoDBObject("_id" -> source_id)).get
    val data = source.get("data").asInstanceOf[BasicDBList]

    var ret:List[Data] = List()

    val it = presses.iterator
    while(it.hasNext) {
        val item = it.next.asInstanceOf[BasicDBObject]

        ret = Data(
            item.get("a").asInstanceOf[String],
            item.get("b").asInstanceOf[String]
        ) :: ret
    }

    ret
}

Please, someone tell me there's a better way.

Ben Dilts
  • 10,535
  • 16
  • 54
  • 85

1 Answers1

1

As you are using case classes anyway, the easiest solution is to just use salat – it will automatically serialize/deserialize to and from a mongo connection with very little boilerplate.

A minor point, but in your code you should be able to simply map across the DBObject holding structure rather than manually mutate the ret variable:

val ret = presses.map { item => Data(…) }

you may need to call .toList if you really want a List (though you may only need Seq or Iterable)

Jed Wesley-Smith
  • 4,686
  • 18
  • 20
  • There's no map method on BasicDBList. Also no toList method, which someone suggested elsewhere. Am I working with the wrong library or something? – Ben Dilts Jun 14 '12 at 22:52
  • I was looking at the MongoDBObject class, not the java driver classes. Looking closer you'd actually want mapResult which you pass a function that takes a Map. You're probably better off using MongoDBObject as the source – that at least has getAs[T] so you don't need to manually cast. MongoDBList is the class that defines toList (and toSeq, toStream etc.) – Jed Wesley-Smith Jun 15 '12 at 07:33
  • Yes, I'd love to use MongoDBObject, but unfortunately findOne().get seems to return a BasicDBObject, which can't be cast to MongoDBObject. – Ben Dilts Jun 15 '12 at 15:20