Mongo Driver Requirements

Provisional Driver API

"Level 0 Driver"

A "Level 0" driver is one that exposes and supports the basic operations of Mongo with no value-add. I think that all operations at level 0 should be "document" operations, keeping anything that smells of an "object operation" out, and in some upper-level layer.

Level 0 Driver Features
Required
  • BSON serialization/deserialization
  • basic operations as listed in this section
  • full cursor support (e.g. support OP_GET_MORE operation)
  • close cursors via OP_KILL_CURSORS
  • database command support
  • handle query errors
  • convert all strings to UTF-8
  • hint, explain, count, $where
  • database profiling: set/get profiling level, get profiling info
  • validate a collection in a database
Optional
  • automatic reconnection
  • buffer pooling
  • advanced connection management (master-server, replica pair, Option_SlaveOk)
  • Tailable cursor support
Server Object

A level 0 driver will implement the following connection options.

Single Server Connection

A driver should be able to connect to a single server. By default this must be localhost:27017, and must also allow the server to be specified by hostname and port.

Mongo m = new Mongo();   // go to localhost, default port
Mongo m = new Mongo(String host, int port);

How the driver does this is up to the driver - make it idiomatic. However, a driver should make it explicit and clear what is going on.

Pair Mode Connection

A driver must be able to support "Pair Mode" configurations, where two instances of Mongo, labeled "left" and "right", and configured for hot-failover.

The driver should determine which of the pair is the current master, and send all operations to that server. In the event of an error, either socket error or a "not a master" error, the driver must restart the determination process. It must not assume the other server in the pair is now the master.

ServerPair sp = new ServerPair(INETAddr...);  // should be able to give only one and it discovers the rest?
Mongo m = new Mongo(sp)

A driver may optionally allow a driver to connect deliberately to the "non-master" in the pair, for debugging, admin or operational purposes.

ServerPair sp = new ServerPair(INETAddr...);  // should be able to give only one and it discovers the rest?
sp.setTarget(ServerPair.SHADOW_MASTER);
Mongo m = new Mongo(sp);
  1. Cluster Mode Connect to master in master-slave cluster
    ServerCluster sc = new ServerCluster(INETAddr...); // again, give one and discover?
    Mongo m = new Mongo(sc);
    

    ## Connect to slave in read-only mode in master-slave cluster

    ServerCluster sc = new ServerCluster(INETAddr...); // again, give one and discover?
    sc.setTarget(...)
    Mongo m = new Mongo(sc);
    
    or maybe make it like *Default/Simple* w/ a flag?
    

Other than that, we need a way to get a DB object :

Mongo m = new Mongo();

DB db = m.getDB(name);

And a list of db names (useful for tools...) :

List<String> getDBNameList();
Database Object

Simple operations on a database object :

/**
 *  get name of database
 */
String    dbName = db.getName();

/**
 * Get a list of all the collection names in this database
 */
List<String> cols = db.getCollectionNames();

/**
 * get a collection object.  Can optionally create it if it
 *  doesn't exist, or just  be strict.  (XJDM has strictness as an option)
 */
Collection coll = db.getCollection(string);

/**
 * Create a collection w/ optional options.  Can fault
 * if the collection exists, or can just return it if it already does
 */
Collection coll = db.createCollection( string);
Collection coll = db.createCollection( string, options);

/**
 * Drop a collection by its name or by collection object.
 * Driver could invalidate any outstanding Collection objects
 * for that collection, or just hope for the best.
 */
boolean  b  = db.dropCollection(name);
boolean  b  = db.dropCollection(Collection);

/**
 * Execute a command on the database, returning the
 * BSON doc with the results
 */
Document d = db.executeCommand(command);

/**
 * Close the [logical] database
 */
void  db.close();

/**
 * Erase / drop an entire database
 */
bool dropDatabase(dbname)

Database Administration

These methods have to do with database metadata: profiling levels and collection validation. Each admin object is associated with a database. These methods could either be built into the Database class or provided in a separate Admin class whose instances are only available from a database instance.

/* get an admin object from a database object. */
Admin admin = db.getAdmin();

/**
 * Get profiling level. Returns one of the strings "off", "slowOnly", or
 * "all". Note that the database returns an integer. This method could
 * return an int or an enum instead --- in Ruby, for example, we return
 * symbols.
 */
String profilingLevel = admin.getProfilingLevel();

/**
 * Set profiling level. Takes whatever getProfilingLevel() returns.
 */
admin.setProfilingLevel("off");

/**
 * Retrieves the database's profiling info.
 */
Document profilingInfo = admin.getProfilingInfo();

/**
 * Returns true if collection is valid; raises an exception if not.
 */
boolean admin.validateCollection(collectionName);
Collection
Basic Ops
/**
 *   full query capabilities - limit, skip, returned fields, sort, etc
 */
Cursor        find(...);

void          insert(...) // insert one or more objects into the collection, local variants on args
void          remove(query) // remove objects that match the query
void          modify(selector, modifier)  // modify all objects that match selector w/ modifier object
void          replace(selector, object)   // replace first object that match selector w/ specified object
void          repsert(selector, object)   // replace first object that matches, or insert  **upsert w/ modifier makes no logical sense*
long          getCount();
long          getCount(query);
Index Operations
void          createIndex( index_info)
void          dropIndex(name)
void          dropIndexes()
List<info>    getIndexInformation()

Misc Operations
document      explain(query)
options       getOptions();
string        getName();
void          close();
Cursor Object
document      getNextDocument()
iterator      getIterator()  // again, local to language
bool          hasMore()
void          close()

"Level 1 Driver"

A "level 1" driver uses a "level 0" driver to add additional functionality. In terms of our history, I think that this is where "ORM"-type of functions should appear.

I think that we might have a variety of level 1 drivers :

  • Level 1 "ORM" Driver : this would support stuff like save(), ensureIndex(), auto create index for _id, resolution of DB Refs, etc
  • Level 1 "GridFS" Driver : this would be a separate and distinct driver that leverages a level 0 driver to do GridFS. No need to combine w/ anything else
Level 1 Database Object
/**
 *  resolve a DBRef, with recursion.  This is a potentially dangerous operation, as the
 *  resulting document graph - and thus the resulting single document, can be arbitrarily
 *  and surprisingly large
 */
Document resolveReference(DBRef ref, boolean recurse);
Level 1 Collection Object
/**
 *
 *  From JS, this is a caching index function that supported the
 *  multiple re-entry and re-initialization model on the app server.  It's a far
 *  more difficult operation outside of the controlled environment of an app server, since
 *  one process has no clue about what other code might be doing (like dropping the index)
 *
 * Put here for completeness
 */
boolean coll.ensureIndex(...);

/**
 *   "saves" a document - this means that if it's already blessed with an _id, the doc
 *   in the database is updated, and if it doesn't have an _id, and _id is injected and then
 *   the doc is inserted into the collection.
 *
 *   There are some interesting implications here now that we're considering relaxing
 *   the constraint on _id being a BabbleOID, and letting it be anything.  There will have to
 *   be some kind of "PKInjector" (see the XJDM) where the programmer can give the level 1
 *   driver an _id factory....
 */
void  coll.save(Document doc);

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

IF YOU HAVE A QUESTION, POST IT TO THE USER GROUP.

These pages are fine for comments, but for questions, your best bet will always be the MongoDB User Group.

blog comments powered by Disqus