h1. PlayMorphia overview

The PlayMorphia module a powerful and yet easy to use framework that provides "MongoDB":http://www.mongodb.org/ access to your Play!framework application. This module is built on top of the famous "Morphia project":http://code.google.com/p/morphia/. 

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

h2. <a name="model">Easy to use Model class</a>

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:

bc. @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:

bc. 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();

h2. <a name="query">Powerful query interface</a>

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:

bc. 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();

h3. <a name="query-order">Sort data returned</a>

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

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

h3. <a name="query-page">Pagination Support</a>

Usually you couldn't present all data in one request. This is why we need "Pagination":http://en.wikipedia.org/wiki/Pagination. Leveraging morphia's query interface, PlayMorphia provides an easy way to support query pagination:

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

h2. Statistics

"Map-Reduce":http://www.mongodb.org/display/DOCS/MapReduce 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:

bc. 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");
...

h2. Entity Lifecycle callbacks

p(note). The content documented in this section are new to PlayMorphia v1.2.4. For life cyle annotations used before v1.2.4 please go to "Morphia documentation":http://code.google.com/p/morphia/wiki/LifecycleMethods

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: 

bc. @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
    }
}

h2. 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.

h3. Morphia interface

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

bc. // get Morphia object
com.google.code.morphia.Morphia morphia = MorphiaPlugin.morphia();
// get Datastore
com.google.code.morphia.Datastore ds = MorphiaPlugin.ds();
// get AdvancedDatastore
com.google.code.morphia.AdvancedDatastore ds = (AdvancedDatastore)MorphiaPlugin.ds();
com.mongodb.DBCollection userCollection = User.col();

h3. The MongoDB Java Driver interface

This is listed here just for curious:

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

p(note). **Give it a try**

"Install the PlayMorphia plugin":http://www.playframework.org/modules/morphia and start developing your application with MongoDB!