ReactiveMongo

A lot of applications these days use a NoSQL database as a result of unstructured data, write scalability, and so on. MongoDB is one such database. According to its website (http://docs.mongodb.org/manual/core/introduction/):

MongoDB is an open source document database that provides high performance, high availability, and automatic scaling.

Key features of MongoDB are:

High performance

High availability (automatic failover, data redundancy)

Automatic scaling (horizontal scalability)

ReactiveMongo is a Scala driver for MongoDB that supports non-blocking and asynchronous I/O operations. There is a plugin for the Play Framework called Play-ReactiveMongo. It is not a Play plugin but it's supported and maintained by the team of ReactiveMongo.

Note

This section requires prior knowledge of MongoDB, so please refer to https://www.mongodb.org/.

To use it, we need to do the following:

  1. Include it as a dependency in the build file:
    libraryDependencies ++= Seq(
      "org.reactivemongo" %% "play2-reactivemongo" % "0.10.5.0.akka23"
    )
  2. Include the plugin in conf/play.plugins:
    1100:play.modules.reactivemongo.ReactiveMongoPlugin
  3. Add the MongoDB server details in conf/application.conf:
    mongodb.servers = ["localhost:27017"]
    mongodb.db = "your_db_name"
    mongodb.credentials.username = "user"
    mongodb.credentials.password = "pwd"

    Alternatively, use the following:

    mongodb.uri = "mongodb://user:password@localhost:27017/your_db_name"

Let's see usage of the plugin with a sample application. We may come across an instance in our application where we allow users to monitor activities on their devices in the form of heat sensors, smoke detectors, and so on.

Before using the device with our application installed on it, the device should be registered with this application. Each device has ownerId, deviceId, its configuration, and product information. So, let's assume that, on registration, we get a JSON in this format:

{
"deviceId" : "aghd",
"ownerId" : "[email protected]"
"config" : { "sensitivity" : 4, …},
"info" : {"brand" : "superBrand","os" : "xyz","version" : "2.4", …}
}

Once a device is registered, the owner can update the configuration or agree to update the product's software. Updating software is handled by the device company, and we only need to update the details in our application.

The queries to the database will be:

  • Insert: This query includes registering a device
  • Update: This query includes updating device configuration or information
  • Delete: This query occurs when a device is unregistered
  • Select: This query occurs when an owner wishes to view the details of the device

    Using Reactive Mongo, the device registration will be:

    def registerDevice(deviceId: String, 
                        ownerId: String, 
                  deviceDetails: JsObject): Future[LastError] = { 
     
        var newDevice = Json.obj("deviceId" -> deviceId, "ownerId" -> ownerId.trim) 
        val config = (deviceDetails  "configuration").asOpt[JsObject] 
        val metadata = (deviceDetails  "metadata").asOpt[JsObject] 
        if (!config.isDefined) 
          newDevice = newDevice ++ Json.obj("configuration" -> Json.parse("{}")) 
        if (!metadata.isDefined) 
          newDevice = newDevice ++ Json.obj("metadata" -> Json.parse("{}")) 
    
        collection.insert[JsValue](newDevice) 
      }

In this snippet, we've built a JSON object from the available device details and inserted it in devices. Here, the collection is defined as follows:

def db = ReactiveMongoPlugin.db

def collection = db.collection("devices")

The insert command accepts the data and its type:

The db operations for fetching a device or removing it are simple,def fetchDevice(deviceId: String): Future[Option[JsObject]] = { 
    val findDevice = Json.obj("deviceId" -> deviceId) 
    collection.find(findDevice).one[JsObject] 
  } 

  def removeDeviceById(deviceId: String): Future[LastError] = { 
    val removeDoc = Json.obj("deviceId" -> deviceId) 
    collection.remove[JsValue](removeDoc) 
  }

This leaves us with just the update query. An update is triggered for a single property of configuration or information, that is, the request has just one field and its new value is this:

{ "sensitivity": 4.5}

Now, a query to update this would be:

    def updateConfiguration(deviceId: String, 
                     ownerId: String, 
                updatedField: JsObject) = { 
    val property = updatedField.keys.head 
    val propertyValue = updatedField.values.head 
    val toUpdate = Json.obj(s"configuration.$property" -> propertyValue) 
    val setData = Json.obj("$set" -> toUpdate) 
    val documentToUpdate = Json.obj("deviceId" -> deviceId, "ownerId" -> ownerId) 
    collection.update[JsValue, JsValue](documentToUpdate, setData) 
  }

When we wish to update a field for a given document in MongoDB, we should add the updated data to the $set field in the query. For example, an equivalent MongoDB query would be as follows:

db.devices.update(
   { deviceId: "aghd" ,"ownerId" : "[email protected]"},
   { $set: { "configuration.sensitivity": 4.5 } }
)
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.18.198