green-leaf-mongo
green-leaf-mongo copied to clipboard
🌱 This extension created on top of official MongoDB Scala Driver and allows to fully utilize Spray JSON, Play JSON or Circe JSON to represent bidirectional serialization for case classes in BSON, as...
green-leaf-mongo
Short description
This extension created on top of official MongoDB Scala Driver and allows to fully utilize Spray JSON or Play JSON to represent bidirectional serialization for case classes in BSON, as well as flexible DSL for MongoDB query operators, documents and collections.
It was introduced in 2019 - Andrii Lashchenko at #ScalaUA - Spray JSON and MongoDB Queries: Insights and Simple Tricks Related slides available at https://www.slideshare.net/lashchenko/spray-json-and-mongodb-queries-insights-and-simple-tricks
Usage
// build.sbt
// https://mvnrepository.com/artifact/io.github.greenleafoss/green-leaf-mongo-core
// `green-leaf-mongo-core` can be used if you want to create your own extension
// https://mvnrepository.com/artifact/io.github.greenleafoss/green-leaf-mongo-spray
libraryDependencies += "io.github.greenleafoss" %% "green-leaf-mongo-spray" % "3.0"
// https://mvnrepository.com/artifact/io.github.greenleafoss/green-leaf-mongo-play
libraryDependencies += "io.github.greenleafoss" %% "green-leaf-mongo-play" % "3.0"
JSON and BSON protocols
GreenLeafMongoJsonBasicFormats
based on DefaultJsonProtocol from Spray JSON and allows to override predefined JsonFormats to make possible use custom serialization in BSON format.
This trait also includes a few additional JsonFormats for LocalDate, LocalDateTime, ZonedDateTime, ObjectId, scala Enumeration and UUID.
PlayJsonProtocol
is a related extension for the Play JSON library and SprayJsonProtocol
for the Spray JSON library.
SprayBsonProtocol
/PlayBsonProtocol
extends related JsonProtocols and overrides Int, Long, BigDecimal, LocalDate, LocalDateTime, ZonedDateTime, ObjectId, scala Enumeration, UUID and Regex JSON formats to represent them in related BSON (MongoDB Extended JSON V2) formats https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/#mongodb-extended-json-v2-usage.
These base protocols allow to simply (de)serialize this instance to and from both JSON and BSON the same way as in Spray JSON:
// MODEL
case class Test(_id: ObjectId, i: Int, l: Long, b: Boolean, zdt: ZonedDateTime)
// JSON
trait TestJsonProtocol extends SprayJsonProtocol:
given testJsonFormat = jsonFormat5(Test)
object TestJsonProtocol extends TestJsonProtocol
// BSON
object TestBsonProtocol extends TestJsonProtocol with SprayBsonProtocol
Once protocols defined, we can make instance of Test case class and use TestJsonProtocol to print related JSON:
val obj = Test(new ObjectId("5c72b799306e355b83ef3c86"), 1, 0x123456789L, true, "1970-01-01")
import TestJsonProtocol.given
println(obj.toJson.prettyPrint)
Output in this case will be:
{
"_id": "5c72b799306e355b83ef3c86",
"i": 1,
"l": 4886718345,
"b": true,
"zdt": "1970-01-01T00:00:00Z"
}
Changing single line of import TestJsonProtocol
to TestBsonProtocol
allows us to (de)serialize this instance to and from BSON:
val obj = Test(new ObjectId("5c72b799306e355b83ef3c86"), 1, 0x123456789L, true, "1970-01-01")
import TestBsonProtocol.given
println(obj.toJson.prettyPrint)
Output in this case will be:
{
"_id": {
"$oid": "5c72b799306e355b83ef3c86"
},
"i": {
"$numberInt": "1"
},
"l": {
"$numberLong": "4886718345"
},
"b": true,
"zdt": {
"$date": {
"$numberLong": "0"
}
}
}
More examples available in implementation of JsonProtocolSpec/BsonProtocolSpec in Spray and Play project modules.
GreenLeafMongoDsl
GreenLeafMongoFilterOps
makes it possible to write queries with a syntax that is more close to real queries in MongoDB, as was implemented in Casbah Query DSL.
"size" $all ("S", "M", "L")
"price" $eq 10
"price" $gt 10
"price" $gte 10
"size" $in ("S", "M", "L")
"price" $lt 100
"price" $lte 100
"price" $ne 1000
"size" $nin ("S", "XXL")
$or( "price" $lt 5, "price" $gt 1, "promotion" $eq true )
$and( "price" $lt 5, "price" $gt 1, "stock" $gte 1 )
"price" $not { $gte (5.1) }
$nor( "price" $eq 1.99 , "qty" $lt 20, "sale" $eq true )
"qty" $exists true
"results" $elemMatch $and("product" $eq "xyz", "score" $gte 8)
// ...
More examples of queries available in GreenLeafMongoFilterOpsSpec.
GreenLeafMongoDao
GreenLeafMongoDao
extends GreenLeafMongoFilterOps
with GreenLeafMongoObservableToFutureOps
to provide a simple DSL to transform Mongo's Observable[Document] instances to Future[Seq[T]], Future[Option[T]] and Future[T].
In addition, this trait provides many useful generic methods such as insert, getById, findById, updateById, replaceById and others.
SprayMongoDao
/PlayMongoDao
are related implementations for Spray and Play JSON libraries.
You can find more details and examples in the dao tests.