Jen-Ming Chung

Map-Reduce with MongoDB and Morphia

Just a note to record the usage of Map-Reduce with MongoDB and Morphia. Firstly, add the Morphia dependency.

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>2.11.2</version>
</dependency>
<dependency>
    <groupId>org.mongodb.morphia</groupId>
    <artifactId>morphia</artifactId>
    <version>0.105</version>
</dependency>

The syntax of MapReduceCommand in Morphia as shown in MapReduceCommand.java:

public MapReduceCommand(
    DBCollection inputCollection, 
    String map, 
    String reduce, 
    String outputCollection, 
    OutputType type, 
    DBObject query) {
    
    // Compiled Code    
}

Here we want to group the sales amount (i.e., subtotal) of each county and exclude the null-subtotal from collection. And without persisting outputs to the new collection. A sample code as shown in below:

public static void main(String[] args) {
    Morphia morphia = new Morphia();
    Datastore ds = morphia.createDatastore(mongo, dbName);

    String map = "function() { emit(this.buyerCounty,this.subtotal);}";
    String reduce = "function(k, v) {return Array.sum(v);}";

    DBObject query = new BasicDBObject("buyerCounty", new BasicDBObject("$ne", null));
    DBCollection collection = ds.getCollection(Order.class);
    MapReduceCommand cmd = new MapReduceCommand(
            collection,
            map,
            reduce,
            null,
            MapReduceCommand.OutputType.INLINE,
            query);
    MapReduceOutput out = collection.mapReduce(cmd);

    for (DBObject o : out.results()) {
        System.out.println(o.get("_id") + " :: " + o.get("value"));
    }
}

This is a portion of results, _id is the county and value is the sales amount of each county. :)

AMERICA :: 22700.0
南投縣 :: 178647.0
台中市 :: 960630.0
台北市 :: 2600085.0
台南市 :: 464212.0
台東縣 :: 8766.0
嘉義市 :: 7612.0
...

References