Reduce code for the common cases of ReactiveMongo usage in Play framework, Scala language.
- Install
 - Usage
 - Methods and properties
 - [Field shortcuts] (#field-shortcuts)
 
Add the library in built.sbt
Play 2.6, Scala 2.11
libraryDependencies += "com.github.andriykuba" % "reactivemongo-shortcuts-play-json" % "2.6.1"
Play 2.5, Scala 2.11
libraryDependencies += "com.github.andriykuba" % "reactivemongo-shortcuts-play-json" % "2.5.19" Suppose, we want to get some field from all documents. The "native" ReactiveMongo code will look like:
def native()(implicit mongo: ReactiveMongoApi):Future[List[JsObject]] = 
  mongo.database
    .map(_.collection[JSONCollection](collectionName)).flatMap(_
      .find(Json.obj(), Json.obj("field" -> 1))
        .cursor[JsObject]()
          .collect[List](-1, 
            Cursor.FailOnError(
              (a: List[JsObject], e: Throwable) => Cursor.Fail(e))))With the Shortcuts it will:
def shortcuts()(implicit mongo: ReactiveMongoApi): Future[List[JsObject]] = 
  all(Json.obj(), Json.obj("name" -> 1))The Shortcuts reduce method "chaining" to one call and use Play Framework JSON to work with data.
To start use shortcuts just extend com.github.andriykuba.play.reactivemongo.shortcuts.Collection
object Users extends Collection{
  val collectionName = "users"
}
...
val allUsersInLondon = Users.all(Json.obj("city" -> "London"))ReactiveMongoApi and ExecutionContext are passed implicitly to all methods but
defineSubCollectionName. ReactiveMongo is asynchronous,
so all methods but defineSubCollectionName return results wrapped in Future.
The name of the collection in MongoDB
Sugar for creating name of higher detailed collection. For example you need to create a collection of user's page visits and you already have the "users" collection. Good naming are:
users
users.pagevisits
So you can do:
object Users extends Collection{
  val collectionName = "users"
}
object UsersPagevisits extends Collection{
  val collectionName = "users.pagevisits"
}Or:
object Users extends Collection{
  val collectionName = "users"
}
object UsersPagevisits extends Collection{
  val collectionName = Users.defineSubCollectionName("pagevisits")
}Shortcut for getting a collection from a database.
So this string
mongo.database.map(_.collection[JSONCollection](collectionName))become as short as
MyCollection.collection()Shortcut for getting a number of documents in the collection.
So this string
mongo.database.map(_.collection[JSONCollection](collectionName)).flatMap(c => c.count())become as short as
MyCollection.count()Fold the collection.
A start value and a fold function are set with the Folder case class.
Projection and sort can also be used.
val folder = Folder(0, (count: Int, doc: JsObject) => {
  count + 1
})
MyCollection.fold(Json.obj("age" -> 20), folder)Fold the collection asynchronously.
A start value and a fold function are set with the FolderM case class.
Projection and sort can also be used.
val folderM = FolderM(0, (count: Int, doc: JsObject) => {
  Future(count + 1)
})
MyCollection.foldM(Json.obj("age" -> 20), folderM)Find all documents. It returns a list of JsObject.
Projection and sort can also be used.
MyCollection.all(Json.obj("age" -> 30))Find zero or one document. It throw an exception if more than one document found. Projection can also be used.
MyCollection.one(Json.obj("name" -> "Adam Smith"))Find zero or one document. It returns first document if more than one document found. Projection and sort can also be used.
MyCollection.first(Json.obj("age" -> 40))Look for the first document in a set of collections with different selects.
Scenario to use - check if there is some document in a set of collection that meets the criteria.
Collection.first(List(
    (TrainsCollection, Json.obj("price" -> Json.obj("$lte" -> 100))),
    (BusesCollection, Json.obj("price" -> Json.obj("$lte" -> 100))),
    (PlanesCollection, Json.obj("price" -> Json.obj("$lte" -> 100)))))Get an optional field from a single document.
Throw an exception if more than one document is found.
Field type T is obligatory.
MyCollection.fieldOpt[Int](Json.obj("name"->"Adam Smith"), "age")Get a field from a single document. It throws an exception if no document
or field are found.
Throw an exception if more than one document is found.
Field type T is obligatory.
MyCollection.field[Int](Json.obj("name"->"Adam Smith"), "age")Get a string field from a single document or empty string if no document or file was found. Throw an exception if more than one document is found.
MyCollection.fieldStringOrEmpty(Json.obj("name"->"Adam Smith"), "address")Update matching document (using findAndModify).
This method is also used for document creation (upsert = true).
MyCollection.update(
  Json.obj("name"->"Adam Smith"), 
  Json.obj("$set" -> Json.obj("age" -> 80)))  
  
  
MyCollection.update(
  mySelector, 
  myDocument,
  upsert = true)   Finds some matching document and creates new document if nothing found.
It throws a DocumentAlreadyExists exception otherwise
MyCollection.createUnique(
  Json.obj("name"->"John Silver"), 
  Json.obj(Json.obj("age" -> 40)))   Inserts a document into the collection and wait for the results.
val document = Json.obj("name"->"Adam Smith")
MyCollection.insert(document)  Remove matching document (using findAndModify).
Return true if document was removed or false if it was not found.
MyCollection.remove(Json.obj("name"->"Adam Smith"))  In beta, look the source code of the FieldShortcuts object