Question

In my play/swagger/reactivemongo application i use the following function in the controller to get a list of results with "EntityID" 8.

@ApiOperation(value = "Gets the item of a specific ID", notes = "Returns an Item", responseClass = "Item", httpMethod = "GET")
@ApiErrors(Array(
new ApiError(code = 400, reason = "Invalid ID supplied"),
new ApiError(code = 404, reason = "Item not found")))
def index = Action { implicit request =>
 Async {
  // test id
  var myVar: Int = 8

  val cursor: Cursor[JsObject] = collection.find(Json.obj("EntityID" -> myVar))
  .sort(Json.obj("_id" -> -1))
  .cursor[JsObject]
  // gather all the JsObjects in a list
  val futureUsersList: Future[List[JsObject]] = cursor.toList

  // transform the list into a JsArray
  val futureUsersListJs: Future[JsArray] = futureUsersList.map { Measurements_live =>
    Json.arr(Measurements_live)
  }

  futureUsersListJs.map { Measurements_live =>
    Ok(Measurements_live)
  }
 }
}

The measurements model:

case class Measurements_live(
EntityID: Int,
SensorID: Int,
Datetime: Date,
Value: String)

object JsonFormats {
import play.api.libs.json.Json
import play.api.data._
import play.api.data.Forms._

implicit val measureFormat = Json.format[Measurements_live]
val measureForm = Form(
  mapping(
    "EntityID" -> number,
    "SensorID" -> number,
    "Datetime" ->  date,
    "Value" -> text)(Measurements_live.apply _)(Measurements_live.unapply _))
}

The problems is that it wont stop loading. There are a total of 35000 objects in the database. I've played with cursor.close() that stops the cursor and that will return some results. What i want is that the cursor automatically closes when all results are returned.

Was it helpful?

Solution

My first instinct is "that's a lot of objects to be fetching in one HTTP request!".

I can't say exactly why this doesn't work but I suspect it's the collating into a Future[List[JsObject]] that is killing the thing.

I would use the version of Cursor.toList() that takes an upTo parameter, set that to a reasonable number (say 100) and then allow the client to specify which page of results they want to see as a parameter. You could even let the client set the page size if you trust them not to get too greedy.

Obviously you'll need to add another clause to your find to get the correct offset for the pagination; if your client just tells you the highest _id value that they've already got, your find() query would still be very simple.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top