MongoDB Datastores

DataNucleus supports persisting/retrieving objects to/from MongoDB datastores (using the datanucleus-mongodb plugin, which utilises the Mongo Java driver). Simply specify your "connectionURL" as follows

datanucleus.ConnectionURL=mongodb:[{server}][/{dbName}] [,{server2}[,server3}]]

For example, to connect to a local server, with database called "myMongoDB"

datanucleus.ConnectionURL=mongodb:/myMongoDB

If you just specify the URL as mongodb then you have a local MongoDB datastore called "DataNucleus", otherwise it tries to connect to the datastore {dbName} at {server}. The multiple {server} option allows you to run against MongoDB replica sets. You then create your PMF/EMF as normal and use JDO/JPA as normal.

The jars required to use DataNucleus MongoDB persistence are datanucleus-core, datanucleus-api-jdo/datanucleus-api-jpa, datanucleus-mongodb and mongo-java-driver

There are tutorials available for use of DataNucleus with MongoDB for JDO and for JPA

Things to bear in mind with MongoDB usage :-

  • Querying can be performed using JDOQL or JPQL. Some components of a filter are handled in the datastore, and the remainder in-memory. Currently any expression of a field (in the same table), or a literal are handled in-datastore, as are the operators &&, ||, >, >=, <, <=, ==, and !=.
  • If you want a query to be runnable on a slave MongoDB instance then you should set the query extension (JDO) / hint (JPA) slave-ok as true, and when executed it can be run on a slave instance.
  • All objects of a class are persisted to a particular "document" (specifiable with the "table" in metadata), and a field of a class is persisted to a particular "field" ("column" in the metadata).
  • Relations : DataNucleus stores the id of the related object(s) in a field of the owning object. When a relation is bidirectional both ends of the relation will store the relation information.
  • Capped collections : you can specify the extension metadata key mongodb.capped.size as the number of bytes of the size of the collection for the class in question.
  • If you want to specify the max number of connections per host with MongoDB then set the persistence property datanucleus.mongodb.connectionsPerHost
  • If you want to specify the MongoDB threadsAllowedToBlockForConnectionMultiplier, then set the persistence property datanucleus.mongodb.threadsAllowedToBlockForConnectionMultiplier

Mapping : Embedded Persistable fields

When you have a field in a class that is of a persistable type you sometimes want to store it with the owning object. In this case you can use JDO/ JPA embedding of the field. DataNucleus offers two ways of performing this embedding

  • The default is to store the object in the field as a sub-document (nested) of the owning document. Similarly if that sub-object has a field of a persistable type then that can be further nested.
  • The alternative is to store each field of the sub-object as a field of the owning document (flat embedding). Similarly if that sub-object has a field of a persistable type then it can be flat embedded in the same way
@PersistenceCapable
public class A
{
    @Embedded
    B b;

    ...
}

This example uses the default embedding, using a nested document within the owner document, and could look something like this

{ "name" : "A Name" ,
  "id" : 1 ,
  "b" : { "name" : "B name" ,
          "description" : "the description"}
}

The alternative would be

@PersistenceCapable
public class A
{
    @Embedded
    @Extension(vendorName="datanucleus", key="nested", value="false")
    B b;

    ...
}

and this will use flat embedding, looking something like this

{ "name" : "A Name" ,
  "id" : 1 ,
  "b_name" : "B name" ,
  "b_description" : "the description"
}

Mapping : Embedded Collection elements

When you have a field in a class that is of a Collection type you sometimes want to store it with the owning object. In this case you can use JDO/ JPA embedding of the field. So if we have

@PersistenceCapable
public class A
{
    @Element(embedded="true")
    Collection<b> bs;

    ...
}

and would look something like this

{ "name" : "A Name" ,
  "id" : 1 ,
  "bs" :
      [
        { "name" : "B Name 1" ,
          "description" : "desc 1"} ,
        { "name" : "B Name 2" ,
          "description" : "desc 2"} ,
        { "name" : "B Name 3" ,
          "description" : "desc 3"}
      ]
}

References

Below are some references using this support