Skip to content

Instantly share code, notes, and snippets.

@loicknuchel
Last active August 29, 2015 14:20
Show Gist options
  • Save loicknuchel/662f04974132f0f2d51c to your computer and use it in GitHub Desktop.
Save loicknuchel/662f04974132f0f2d51c to your computer and use it in GitHub Desktop.
Problem with Reactivemongo & Aggregation

I'm using Play 2.3.7, Mongo 2.4.8 and reactivemongo 0.10.5 and I've got some surprising things...

When start the shell and run :

db.Exponents.aggregate([
  {$match: {eventId: {$in: ["3dac7440-f8e5-497d-8b0b-77127d16e1ae", "fcb07f0c-2ff3-4408-b83e-8f42d6a00112"]}}},
  {$group: {_id: "$eventId", eventCount: {$sum: 1}}}
])

I get this (as expected) :

{
  "result" : [
    {"_id" : "fcb07f0c-2ff3-4408-b83e-8f42d6a00112", "eventCount" : 1},
    {"_id" : "3dac7440-f8e5-497d-8b0b-77127d16e1ae", "eventCount" : 2}
  ],
  "ok" : 1
}

But when I try to do this query with reactivemongo I get the entiere collection as a result (like db.Exponents.find())... My Scala code :

def countForList(values: Seq[String], collection: JSONCollection, fieldName: String = "uuid") = {
  import play.modules.reactivemongo.json.BSONFormats._
  val matchPredicate = Json.obj(fieldName -> Json.obj("$in" -> values))
  val groupPredicate = Json.obj("_id" -> ("$" + fieldName), "count" -> Json.obj("$sum" -> 1))
  val commandDoc = BSONDocument(
    "aggregate" -> collection.name,
    "$pipeline" -> BSONArray(
      BSONDocument("$match" -> BSONFormats.BSONDocumentFormat.reads(matchPredicate).get),
      BSONDocument("$group" -> BSONFormats.BSONDocumentFormat.reads(groupPredicate).get)))

  collection.db.command(RawCommand(commandDoc)).map { result =>
    play.Logger.info("\n\n\n\n")
    play.Logger.info("values: " + values)
    play.Logger.info("collection: " + collection.name)
    play.Logger.info("matchPredicate: " + matchPredicate)
    play.Logger.info("groupPredicate: " + groupPredicate)
    play.Logger.info("command: " + Json.toJson(commandDoc))
    play.Logger.info("RESULTS: " + Json.toJson(result) + "\n\n")
  }
}

And my logs :

[info] application - values: List(3dac7440-f8e5-497d-8b0b-77127d16e1ae)
[info] application - collection: Exponents
[info] application - matchPredicate: {"eventId":{"$in":["3dac7440-f8e5-497d-8b0b-77127d16e1ae"]}}
[info] application - groupPredicate: {"_id":"$eventId","count":{"$sum":1}}
[info] application - command: {"aggregate":"Exponents","$pipeline":[{"$match":{"eventId":{"$in":["3dac7440-f8e5-497d-8b0b-77127d16e1ae"]}}},{"$group":{"_id":"$eventId","count":{"$sum":1.0}}}]}
[info] application - RESULTS: {"result":[{"_id":{"$oid":"5548f79f5c0c00f12340fa1a"},"uuid":"402cf7df-b649-471f-a51d-4fd526fec8f4","eventId":"3dac7440-f8e5-497d-8b0b-77127d16e1ae","name":"First 2","description":"","company":"SalooN","place":{"ref":"","name":""},"tags":["a","b","c","d"],"created":1.4308453434E+12,"updated":1430850752629},{"uuid":"41b2737a-a922-4230-998d-9f428fbec2dd","eventId":"3dac7440-f8e5-497d-8b0b-77127d16e1ae","name":"Second","description":"","company":"Knu Corp.","place":{"ref":"","name":""},"tags":[""],"created":1430851413623,"updated":1430851413623,"_id":{"$oid":"55490f555c0c00792a40fa1b"}},{"uuid":"62dd7ba8-43bc-4ed3-b3cd-99c378e26892","eventId":"fcb07f0c-2ff3-4408-b83e-8f42d6a00112","name":"AAA","description":"","company":"AAA","place":{"ref":"","name":""},"tags":[""],"created":1430851524294,"updated":1430851524294,"_id":{"$oid":"55490fc45c0c008d2a40fa1d"}}],"ok":1.0}

According to Reactivemongo documentation the command seems correct :

{
  "aggregate":"Exponents",
  "$pipeline":[
    {"$match":{"eventId":{"$in":["3dac7440-f8e5-497d-8b0b-77127d16e1ae"]}}},
    {"$group":{"_id":"$eventId","count":{"$sum":1.0}}}
  ]
}

But event a mistake on my side, the result is quite unexpected :

{
  "result":[
    {"uuid":"402cf7df-b649-471f-a51d-4fd526fec8f4","eventId":"3dac7440-f8e5-497d-8b0b-77127d16e1ae","name":"First 2","description":"","company":"SalooN","place":{"ref":"","name":""},"tags":["a","b","c","d"],"created":1.4308453434E+12,"updated":1430850752629,"_id":{"$oid":"5548f79f5c0c00f12340fa1a"}},
    {"uuid":"41b2737a-a922-4230-998d-9f428fbec2dd","eventId":"3dac7440-f8e5-497d-8b0b-77127d16e1ae","name":"Second","description":"","company":"Knu Corp.","place":{"ref":"","name":""},"tags":[""],"created":1430851413623,"updated":1430851413623,"_id":{"$oid":"55490f555c0c00792a40fa1b"}},
    {"uuid":"62dd7ba8-43bc-4ed3-b3cd-99c378e26892","eventId":"fcb07f0c-2ff3-4408-b83e-8f42d6a00112","name":"AAA","description":"","company":"AAA","place":{"ref":"","name":""},"tags":[""],"created":1430851524294,"updated":1430851524294,"_id":{"$oid":"55490fc45c0c008d2a40fa1d"}}
  ],
  "ok":1.0
}

Any tip on what goes wrong ?

Thanks !

@loicknuchel
Copy link
Author

Thanks to @twillouer the solution is to remove the $ of $pipeline...

val commandDoc = BSONDocument(
  "aggregate" -> collection.name,
  "pipeline" -> BSONArray(
    BSONDocument("$match" -> BSONFormats.BSONDocumentFormat.reads(matchPredicate).get),
    BSONDocument("$group" -> BSONFormats.BSONDocumentFormat.reads(groupPredicate).get)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment