/play-morphia

Provide mongodb access service to play.db.Model via Morphia

Primary LanguageJavaApache License 2.0Apache-2.0

Play!Framework official web site is close to module update. Please follow https://gist.github.com/2868365 to get new morphia module version

Break changes: play-morphia 1.5.0 update morphia library to org.mongodb.morphia 0.107. Please do text replacement in your application from “com.google.code.morphia” to “org.mongodb.morphia”

PlayMorphia overview

The PlayMorphia module a powerful and yet easy to use framework that provides MongoDB access to your Play!framework application. This module is built on top of the famous Morphia project.

Stick to the philosophy of Play!Framework, PlayMorphia provides a data layer infrastructure to help developer focusing on the business logic instead of technical details. PlayMorphia is by far the most welcome MongoDB access module in the community

Thanks to the super powerful code enhancement mechanism of Play!framework, we could bring you a very simple model class and provides all weapons you need in the same time.

You define a model class as:

@Entity
public class User extends Model {
    public String fName;
    public String lName;
    public String region;
    public String department;
    public int age;
    public int score;
public User(String firstName, String lastName, region, department) { this.fName = firstName; this.lName = lastName; this.region = region; this.department = department; }

}

You use the model in your application in the following ways:

User user = new User("John", "Smith", "AU", "IT").save()
Object id = user.getId();
...
User user = User.findById(id);
...
user.region = "ZH";
user.department = "Sales";
user.save();
...
user.delete();

As shown above you could use Model.findById interface to fetch an entity by it’s identifier. But how to query data using non-id properties? Don’t worry, PlayMorphia provides comprehensive query interfaces enable you to dig out every bit of data in whatever way you want:

List<User> allUsers = User.findAll();
...
List<User> auUsers = User.find("region", "AU").asList();
...
List<User> auITUsers;
auITUsers = User.find("region department", "AU", "IT").asList();
auITUsers = User.find("region,department", "AU", "IT").asList();
auITUsers = User.find("byRegionAndDepartment", "AU", "IT").asList();
auITUsers = User.q().filter("region", "AU").filter("department", "IT").asList();
auITUsers = User.q().findBy("region department", "AU", "IT").asList();...
...
List<User> auLittleUsers = User.find("region", "AU").filter("age <", 18).asList();

It’s bit of easy to sort data in ascend or descend order:

List<User> usersByAgeAsc = User.q().order("age").asList();
...
List<User> usersByAgeDes = User.q().order("-age").asList();

Usually you couldn’t present all data in one request. This is why we need Pagination. Leveraging morphia’s query interface, PlayMorphia provides an easy way to support query pagination:

List<User> users = User.q().offset(30).limit(10).asList();

Statistics

Map-Reduce is no doubt a powerful weapon provided by MongoDB for data aggregation. However it’s by no means an easy tool in terms of Java programming. PlayMorphia module hide all the complexity behind a set of simple clean interfaces:

long userCount = User.count();
long auUserCount = User.find("region", "AU").count();
int minAge = User._min("age");
int maxAge = User._max("age");
int totalScore = User._sum("score");
int averageScore = User._average("score");
...
// group aggregation interface is still so easy to use
AggregationResult minValueDistribution = User.groupMin("age", "region department");
int minAge_AU_IT = (int)minValueDistribution.get("region department", "AU", "IT");
...

Entity Lifecycle callbacks

Sometimes it’s interesting to listen to the lifecycle events of an entity and proceed with relevant logics. For example, you want to log an entry input, or you want to send an notification email on entry removed. PlayMorphia provides a set of lifecycle annotations to mark the methods to be called when certain event triggered:

@Entity public class User {
    public String fName;
    public String lName;
    @OnLoad void beforeLoad() {
        Logger.info("user entity about to load data from mongodb");
    }
    @Loaded void afterLoad() {
        Logger.info("user entity now filled with data from mongodb");
    }
    @OnAdd void beforeAddNew() {
        Logger.info("About to create new user record");
    }
    @Added void afterAddNew() {
        Logger.info("new user record created in the database");
    }
    @OnUpdate void beforeSaveUpdated(){
        Logger.info("About to persist updated user into database");
    }
    @Updated void afterUpdatedSaved() {
        Logger.info("Updated user data persisted to the database");
    }
    @OnDelete void beforeDelete() {
        Logger.info("About to delete a user record from the database");
    }
    @Deleted void afterDelete() {
        Logger.info("This user record is removed from mongodb");
    }
    @OnBatchDelete static void beforeBatchDelete(MorphiaQuery q) {
        Logger.info("About to delete all records specified by the query");
    }
    @BatchDeleted static void afterBatchDelete(MorphiaQuery q) {
        Logger.info("Records specified by the query has been deleted";
        // Note q.count() will always return 0 in this method as the
        // records specified by the query has already been removed
    }
}

Low level interface

The facilities directly provided by PlayMorphia can cover almost all cases you could encountered when dealing with MongoDB. Though I want to say that , you could go to the low level interfaces exposed by PlayMorphia.

Morphia interface

Once you installed PlayMorphia you get everything out of Morphia already. But trust me you almost have no chance to use them:

// get Morphia object
org.mongodb.morphia.Morphia morphia = MorphiaPlugin.morphia();
// get Datastore
org.mongodb.morphia.Datastore ds = MorphiaPlugin.ds();
// get AdvancedDatastore
org.mongodb.morphia.AdvancedDatastore ds = (AdvancedDatastore)MorphiaPlugin.ds();

The MongoDB Java Driver interface

This is listed here just for curious:

// get Mongo object
com.mongodb.Mongo mongo = MorphiaPlugin.ds().getMongo();

You can also set Mongo driver options in conf/application.conf like this:

## Mongo driver configuration
morphia.driver.threadsAllowedToBlockForConnectionMultiplier=10
morphia.driver.connectionsPerHost=20
morphia.driver.slaveOk=true

Give it a try

Install the PlayMorphia plugin and start developing your application with MongoDB!