Query in Java as in Mongo shell
db.friends.find({age: {$gt: 18}})
Java Driver
friends.find(new BasicDBObject("age",new BasicDBObject("$gt",18)))
friends.find("{age: {$gt: 18}}").as(Friend.class)

Faithful spiritMongo query language isn't available in Java, Jongo fixes that. Copy/paste your queries to string.

Object orientedSave & find objects into & from collections. Use embedded Jackson marshalling or your own.

Wood solidAs fast as Mongo Java driver. Open source, fully tested & made of rock solid librairies.

Set up

First install Mongo, then choose a driver's version, finally download Jongo and you're all set.

DB db = new MongoClient().getDB("dbname");

Jongo jongo = new Jongo(db);
MongoCollection friends = jongo.getCollection("friends");

MongoCursor<Friend> all = friends.find("{name: 'Joe'}").as(Friend.class);
Friend one = friends.findOne("{name: 'Joe'}").as(Friend.class);



Passing an object to the save(..) method will do the job. See mapping section for objects defintion.

Friend joe = new Friend("Joe", 27);;
joe.age = 28;;


Update syntax is a bit different than in Mongo shell: modifier query has to be passed using with(..). You can update with a String or with an object. You can also parameterize queries with # (using primitives or complex objects), see query templating for more details.

friends.update("{name: 'Joe'}").with("{$inc: {age: 1}}");
friends.update("{name: 'Joe'}").upsert().multi().with("{$inc: {age: 1}}");

friends.update("{name: 'Joe'}").with(new Friend(..));
friends.update("{name: 'Joe'}").with("{$set: {address: #}}", new Address(..));


Insert works as in Mongo shell.

friends.insert("{name: 'Joe', age: 18}");

friends.insert(new Friend(..));
friends.insert(new Friend(..), new Friend(..));


Remove works as in Mongo shell.

friends.remove("{name: 'Joe'}");
friends.remove(new ObjectId("4c...e"));

Object Mapping

Query results are automatically mapped to objects. By default, this relies on Jackson; it respects document structure, handles lists and ignores missing attributes. It just needs a no-arg constructor, even private (if the object has to be immutable, @JsonCreator annotation can be used instead).

_id is a unique identifier available on every Mongo document. If it isn't setted, it is generated. To handle it with Jongo, one attribute has to be named _id or annotated with @MongoId (alias for @JsonProperty("_id")). It can be handled with the dedicated ObjectId class or with a simple String — annotated @MongoObjectId.

Careful, saving a document with a custom _id (ie: any Java type, other than array, so long as it is unique) always involves to set it manually before persisting.

public class Friend {
    // manual
    private long _id;

public class Friend {
    // manual
    private long key;
public class Friend {
    // manual
    private String key;
public class Friend {
    // auto
    private String _id;
public class Friend {
    @MongoId // auto
    private String key;
public class Friend {
    // auto
    private ObjectId _id;


JSON properties are automatically mapped to their equivalent object attributes (and complex ones mapped as sub-attributes). No extra annotations needed. To ignore a pojo attribute, annotate it with @JsonIgnore.
For fine grained control over (un)marshalling, configure Jongo mapper or create your own.

Handling polymorphism

To handle polymorphism of Java objects, a field containing the class name must be set into the Mongo document. One can persist a Fox (sub-class of Friend) and manipulate it as a Friend. This feature is provided out-of-the-box by Jackson. Using another (un)marshaller implies extra work.

public class Friend {
    int age;
public class Fox extends Friend {
    String name, color;
} Fox("fantastic", "red-haired"));
Friend friend = friends.findOne("{name:'fantastic'}").as(Friend.class);
Fox fantastic = (Fox)friend;

Using a singular reserved name, like _class, for this field is a good idea.


Find & FindOne

Query syntax is almost the same as in Mongo shell: copy/paste, it just works.
Strings have to be escaped with single quotes "{name: 'Joe'}", numbers don't "{age: 18}".

MongoCursor<Friend> all = friends.find("{name: 'Joe'}").as(Friend.class);

Friend joe = friends.findOne("{name: 'Joe'}").as(Friend.class);
Friend joe = friends.findOne(new ObjectId("4c...e")).as(Friend.class);

Field names need quotes when using dot notation "{'': 'London'}".

Projection or Field selection

Field selection aka. partial loading is not written as in Mongo shell: Jongo exposes a projection(..) method. A json selector must be provided: {field: 1} to include it, {field: 0} to exclude it.

friends.find().projection("{lastname: 1, address: 1}").as(Friend.class);


Documents can be sorted in ascending or descending order using a json selector: {field: 1} for ascending, {field: -1} for descending.

friends.findOne().orderBy("{firstname: 1}").as(Friend.class);
friends.find().sort("{firstname: 1}").as(Friend.class);
friends.find().sort("{lasttname: -1}").as(Friend.class);

Skip and Limit

Behaviour similar to Java driver DBCursor.



Behaviour similar to Java driver Find.hint(..).

friends.find().hint("{age: 1}").as(Friend.class);

Query modifiers

Query modifiers can be setted on DBCursor by implementing QueryModifier.

friends.find().with(new QueryModifier() {
     public void modify(DBCursor cursor) {
         cursor.addSpecial("$maxScan", 1);

Closing cursor

You can close cursor manually by calling close() method on MongoCursor

MongoCursor<Friend> cursor = friends.find().as(Friend.class);
//iterate over it


As said in the mapping section, _id identifier can be manipulated with a String annotated with @MongoObjectId. If you want to completly avoid using driver's ObjectId, Jongo offers the Oid class.

import static org.jongo.Oid.withOid;

Friend joe = new Friend(); // @MongoObjectId String _id;
friends.find(withOid(; // instead of new ObjectId(

Query templating

Almost all queries in Jongo can be templated: add anchors # as follow. Binded parameters can be BSON Primitives or any complex type made of those.

friends.find("{name:#, age:#}", "Joe", 18); //→ will produce {name: 'Joe', age: 18}
friends.find("{address: #}", new Address(..)); //→ will marshall Address object
List<String> ages = Lists.newArrayList(22, 63);
friends.find("{age: {$in:#}}", ages); //→ will produce {age: {$in:[22,63]}}

Projections can also be templated


Regular expressions

Classic $regex: 'jo.*' operator works in Jongo. It worth mentioning that Pattern.compile("jo.*") also does. Unluckily, JavaScript syntax /jo*/g is not available in Mongo Java Driver and Jongo cannot use it yet.

collection.findOne("{name: {$regex: #}}", "jo.*").as(Friend.class);
collection.findOne("{name:#}", Pattern.compile("jo.*")).as(Friend.class);


Behaviour similar to Java driver DBCollection.count(..).

friends.count("{name: 'Joe'}");

Note that a count() method is also available on MongoCursor, behaviour similar to DBCursor.count()

MongoCursor<Friend> cursor = friends.find().as(Friend.class);
int nbResults = cursor.count();


Behaviour pretty similar to Java driver db.runCommand(..).

jongo.runCommand("{geoNear: 'friends', near: [48,9]}").as(GeoNearResult.class);

You can map command results to a single result field.

jongo.runCommand("{geoNear: 'friends', near : [48.690,9.140]}")



Distinct syntax is almost the same as Find/FindOne operations. Optional query can be setted using query(..) method

List<String> names = friends.distinct("name").as(String.class);
List<Address> addresses = friends.distinct("address").query("{name: 'Joe'}").as(Address.class);

Aggregation Framework

Careful, this feature is only available in the Mongo v2.2 release. All aggregation operators are supported $project, $match, $limit, $skip, $unwind, $group, $sort and can be piped using and(..) method


Advanced query

Geospacial indexing

Using Mongo geospacial capacities requires an index and some BSON operators.

friends.ensureIndex("{address: '2d'}");
friends.find("{address: {$near: [0, 0], $maxDistance: 5}}").as(Address.class);

ReadPreference & WriteConcern

Read and write behaviors can be configured on a query basis. ReadPreference defines how multiple instances are readed, WriteConcern defines how writes are done.


Complete query syntax

Mongo uses a behind the scenes syntactic sugar for methods like sort(..), limit(..) and others. The complete expression can also be used in Jongo.

friends.find("{$query: {}, $maxScan: 2}").as(Friend.class);
friends.find("{$query: {}, $orderby: {name: 1}}").as(Friend.class);



Jongo is lighting fast. Not because it is made of ancient wood and magic stones, it just binds Jackson — the fastest Java json (un)marshalling library — to Mongo Java driver with the slightest glue code possible.

Since 0.3, Jongo uses Mongo Java driver at a deeper level to enhance performance. Instead of converting results into strings and unmarshalling strings into objects, it works at byte[] level (query marhalling works the same since 1.0).

Several microbenchmarks (using Caliper & Yourkit) highlight this release net improvements: Jongo 0.3 is 6 times faster than Jongo 0.2, which make it as fast as the driver! Have a look at find microbenchmark and save microbenchmark, and at their implementations (find & save).

Not all benchmarks accurately reflect real world performance; more on microbenchmarks.

Configuring Jongo Mapper

Jongo comes with a custom Jackson configuration that can be extended.

DB db = new Mongo().getDB("dbname");

Jongo jongo = new Jongo(db,
  new JacksonMapper.Builder()
      .registerModule(new JodaModule())

Mapper interface

Jongo constructor comes with an optional parameter: Mapper. This interface has a provided JacksonMapper implementation which defines the defaut (un)marshalling behavior of Jongo. JacksonMapper.Builder allows to alter this configuration as you see fit.

Features on/off

Default JacksonMapper.Builder() comes with predefined features for the embedded Jackson ObjectMapper (see VisibilityModifier and PropertyModifier). Those can be overridden and extended with enable(..) and disable(..) methods.


Jackson Module is a set of (un)marshalling configuration. Hanlding Joda dates, for example, can be done with this Jackson module and the registerModule(..) method.

Json view

Jackson @JsonView allows to filter an object attributes on (un)marshalling. Once Jongo is configured to use the Public view (as in the previous configuration), the gender attribute will be ignored even if it exists in Mongo.

Careful, when no view is defined, Jackson ignore annotations — which means every attribute is visible. Views can be used for marshalling-only or unmarshalling-only if needed.

public class Friend {
    private String _id;

    private String gender;

public class Views {
    public static class Public {}
    public static class Private extends Public {}


Jongo uses the MapperModifier interface to configure a JacksonMapper. Looking at one implementation give a good feeling of how it can be used to further configure a JacksonMapper.

Reader & WriterCallback

In certain circumstances, modifying Jackson ObjectReader or ObjectWriter will be useful. JacksonMapper offers one default ReaderCallback and one WriterCalback for that purpose, they can be replaced if needed.

For more options, refer to Jackson documentation.

Using a custom Mapper

Instead of Jackson, one can provide his own implementation of Mapper.

public class GsonMapper extends Mapper {
    Marshaller getMarshaller() { ... }
    Unmarshaller getUnmarshaller() { ... }
    ObjectIdUpdater getObjectIdUpdater() { ... }
    QueryFactory getQueryFactory() { ... }

Jongo jongo = new Jongo(mongo.getDB("dbname"), new GsonMapper());

Using a custom ResultHandler

If one prefers to manually handle objects (ie. without unmarshaller), he can implements ResultHandler. Each result entity will be passed to the inherited handle(DBObject result) method.

MongoCursor<Integer> ages = friends.find("{name: 'Joe'}").map(
    new ResultHandler<Integer>() {
        public Integer handle(DBObject result) {
            //do manual stuff here
            return result.get("age");

Exposing objects through web services

Because Jongo uses custom Jackson annotations @MongoId and @MongoObjectId, your pojos can be exposed through Jersey (or Spring or any web services library) without any conflicts.

Release notes (1.2→1.3.0)

Previous releases: 1.2, 1.1, 1.0, 0.4, 0.3, 0.2, 0.1

Better handling of @MongoId and @MongoObjectId (thanks to Christian Trimble)
thanks to Christian Trimble
thanks to Julien Lavergne
thanks to Arcadius Ahouansou
thanks to Stefan Fuchs


Jongo relies upon Jackson 2.7.3, Bson4Jackson 2.7.0 and Mongo Java Driver 3.0+. Its Maven dependency, an OSGI compliant jar, comes with the first two, you have to provide a dependency to the driver.

Jongo is deployed into OSS Sonatype (Maven repository hosting service for open source projects).
Add the following dependency to your pom.xml