Pregunta

I am slightly confused on how to retrieve an individual document from MongoDB using Casbah in my Scalatra project. Currently, I have some code that hypothetically looks like the following:

get ("/dogs") {
    val collar_id = params.getOrElse("collar_id", 1)
    val mongoColl = mongoDb("pets")("dogs")     
    val o: DBObject = MongoDBObject("collar_id" -> collar_id)
    val b = mongoColl.findOne(o)

    b.json_document
}

In this case, the document b has a json_document field that has all of the data I need to get rendered in the response as JSON. The problem is, I don't seem to be querying MongoDB properly here using Casbah. The equivalent of how I'd query this using mongodb's client would be:

db.dogs.findOne({collar_id: 5})

What's the correct way to write my query code above to get similar results? Passing in collar_id as a string or Int doesn't seem to work. Also get an error on returning b.json_document:

 value json_document is not a member of Option[mongoColl.T]
¿Fue útil?

Solución

Are params a map of ints or strings? If the var collar_id is a string, but you store it as an int when you query it wont find any results.

Here's an example of ensuring collar_id is a valid int based on params of Map[string, Any]:

val collar_id = params.getOrElse("collar_id", "1").toString match {
    case x if x.forall(Character.isDigit) => x.toInt
    case _ => 1
}

Otros consejos

You can use the getAs method on the params value:

get("/api/dogs/:collarId") {

  val query = for {
    collarId <- params.getAs[Long]("collarId")
    collar <- mongoColl.findOne(MongoDBObject("collar_id" -> collarId))
  } yield collar

  query match {
    case Some(x) => x
    case None => halt(404)
  }

}

This works also great with scalaz's \/ type:

get("/api/dogs/:collarId") {

  for {
    collarId <- params.getAs[Long]("collarId") \/> BadRequest()
    collar <- mongoColl.findOne(MongoDBObject("collar_id" -> collarId)) \/> NotFound()
  } yield collar

}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top