Skip to content
Stephan Bösebeck edited this page Aug 29, 2014 · 2 revisions

Count

Counting is quite easy, call countAll() on any given Query-instance. Please keep in Mind: countAll() does not take limit() or skip() into account, always returns the number of all possible matches to the query.

Distinct values

Morphium supports distinct queries (since 1.4.07) and allows you to get a list of values existing in the query result. Have a look, how to use it:

List<UncachedObject> lst = new ArrayList<UncachedObject>();
        for (int i = 0; i < 100; i++) {
            UncachedObject uc = new UncachedObject();
            uc.setCounter(i % 3);
            uc.setValue("Value " + (i % 2));
            lst.add(uc);
        }
        MorphiumSingleton.get().storeList(lst);

        List values = MorphiumSingleton.get().distinct("counter", UncachedObject.class);
        assert (values.size() == 3) : "Size wrong: " + values.size();
        for (Object o : values) {
            log.info("counter: " + o.toString());
        }
        values = MorphiumSingleton.get().distinct("value", UncachedObject.class);
        assert (values.size() == 2) : "Size wrong: " + values.size();
        for (Object o : values) {
            log.info("Value: " + o.toString());
        }

The output would look like:

19:03:17,211 INFO  [main] DistinctGroupTest: counter: 0
19:03:17,211 INFO  [main] DistinctGroupTest: counter: 1
19:03:17,211 INFO  [main] DistinctGroupTest: counter: 2
19:03:17,213 INFO  [main] DistinctGroupTest: Value: Value 0
19:03:17,213 INFO  [main] DistinctGroupTest: Value: Value 1

Here the call to "distinct" returns a list ov values, which (of course) might be of any type. Those values are not unmarshalled, which means, if this would contain a sub-document, you will get a list of BasicDBObject.

Group Function

Morphium has support for MongoDB's group-Function (similar to SQL group by). Here is an example:

        HashMap<String, Object> initial = new HashMap<String, Object>();
        initial.put("count", 0);
        initial.put("sum", 0);
        DBObject ret = MorphiumSingleton.get().group(MorphiumSingleton.get().createQueryFor(UncachedObject.class), initial,
                "data.count++; data.sum+=obj.counter;", "data.avg=data.sum/data.count;");
        log.info("got DBObject: " + ret);

Producing output:

19:05:19,517 INFO  [main] DistinctGroupTest: got DBObject: [ { "count" : 100.0 , "sum" : 5050.0 , "avg" : 50.5}]

some Explanations:

parameter query is the query to execute, might be an empty one for the whole collection initial is a Map containing the data object that is manipulated by the javascript code in 'jsReduce' and 'jsFinalize' jsReduce is the call to reduce the data to what is needed, here count all objects and sum up the values. If you did not define the reduce function yourself in the given string, a function (obj,data) { and the closing brackets are added jsFinalize: Javascript code to finalize the data, if no function is specified in the string, function(data) {and the closing brackets are added. Here: finalize calculates the avg of all values you might also add fields to group by. Those might either all be not prefixed or prefixed with a - to have it not grouped by that the return value is a list of DBObject, containing at least the values from the initialMap given in the call!

Attention this might cause heavy load on the mongo if the correct indices are missing.