Tuesday, 3 January 2012

MongoDB and CRUD, or should that be ISUD

I started this blog to remind myself of the solutions to development issues I have along the way and as a general hinting mechanism to remind myself what is going on when I have been away from it for a while. If any of this means that someone else reading this saves themself a world of hurt or going down the rabbit-hole of death, then I'm glad that recording it publically rather than privately was helpful (though conversely, it is always important to learn from one's owner experiences).

In my first posting Simple mongodb equivalents, I wanted to remind myself of some of the basic differences around selection between SQL and NoSQL, and to give concrete examples of what this would look like in Java. In this posting I'll go through the next stage, the hinting mechanism for CRUD.

For those that associate crud with filth, flattery, disgust or disappointment, then you may be on the wrong blog. CRUD stands for CREATE, RETRIEVE, UPDATE, DELETE - though the RETRIEVE is usually replaced by get or SELECT at implemention and CREATE is replaced with INSERT. So, perhaps I'll call it ISUD instead.

First, set up the database, a user and set up an index.
use isud
db.addUser("username", "password")
db.auth("username", "password")
db.isud.ensureIndex({"name" : 1, "type" : 1}, {unique : 1})
view raw isudsetup hosted with ❤ by GitHub

The CREATE (or INSERT) of CRUD (or ISUD)
Here we a setting up some basic data in a collection named 'stuff' that lives in the 'isud' database.

...this is how you would do it from the mongo shell...
db.stuff.insert({"name" : "Red Rum", "owner" : "Noel Le Mare", "wins" : [ { "year" : "1973"}, { "year" : "1974"}, { "year" : "1977"}]})
db.stuff.insert({"name" : "Seagram", "owner" : "Sir Derek Parker", "wins" : [ { "year" : "1991"}]})
view raw isudinsertshell hosted with ❤ by GitHub

...and the Java implementation...
//assume parameter 'stuff' is a json document passed to the method, a string as defined above, ie {"name" : "Seagram", "owner" : "Sir Derek Parker", "wins" : [ { "year" : "1991"}]}
try {
Mongo mongo = new Mongo("localhost" , 27017);
DB db = mongo.getDB( "isud" );
DBCollection collection = db.getCollection("stuff");
DBObject dbo = (DBObject)JSON.parse(stuff);
collection.insert(dbo);
}
view raw isudinsert.java hosted with ❤ by GitHub


The RETRIEVE (or SELECT) of CRUD (or ISUD)
The selection or retrieval of a document from the collection 'stuff' can be rather powerful, as per Simple mongodb equivalents.

...this is how you would do it from the mongo shell...
db.stuff.find({"name" : "Seagram"})
{ "_id" : ObjectId("4f02ffa8b8eea0b686189c8e"), "name" : "Seagram", "owner" : "Sir Derek Parker", "wins" : [ { "year" : "1991" } ] }
view raw isudselectshell hosted with ❤ by GitHub

...and the Java implementation...
//assume parameter 'name' is passed to the method, ie Seagram
try {
Mongo mongo = new Mongo("localhost" , 27017);
DB db = mongo.getDB( "isud" );
DBCollection collection = db.getCollection("stuff");
DBObject query = new BasicDBObject();
query.put("name", name);
//there is an index on name, so you can use findOne which returns a DBObject rather than a DBCursor
collection.findOne(query);
}
view raw isudselect.java hosted with ❤ by GitHub

Now let's do a similar thing but this time specify the fields we want returned.

...this is how you would do it from the mongo shell...
db.stuff.find({"name" : "Seagram"}, {"name" : "1"})
{ "_id" : ObjectId("4f02ffa8b8eea0b686189c8e"), "name" : "Seagram" }

...and the Java implementation...
//assume parameter 'name' is passed to the method, ie Seagram
try {
Mongo mongo = new Mongo("localhost" , 27017);
DB db = mongo.getDB( "isud" );
DBCollection collection = db.getCollection("stuff");
DBObject query = new BasicDBObject();
query.put("name", name);
//we only want to get back these fields
DBObject fields = new BasicDBObject();
fields.put("name", 1);
//there is an index on name, so you can use findOne which returns a DBObject rather than a DBCursor
collection.findOne(query, fields);
}


The UPDATE of CRUD
Everyone knows his name was Eric, not Derek, so let's fix that with an update.

...this is how you would do it from the mongo shell...
db.stuff.update({"name" : "Seagram"}, {$set : {"owner" : "Sir Eric Parker"}});
view raw isudupdateshell hosted with ❤ by GitHub

...and the Java implementation...
//assume parameter 'stuff' is passed to the method and contains all the name value pairs (NVPs) defined in the document including the _id NVP
try {
Mongo mongo = new Mongo("localhost" , 27017);
DB db = mongo.getDB( "isud" );
DBCollection collection = db.getCollection("stuff");
DBObject dbo = DBObjectFactory.fromJson(stuff);
collection.save(dbo);
}
//specifically to mirror the shell
try {
Mongo mongo = new Mongo("localhost" , 27017);
DB db = mongo.getDB( "isud" );
DBCollection collection = db.getCollection("stuff");
DBObject query = new BasicDBObject();
query.put("name", "Seagram");
DBObject set = new BasicDBObject();
set.put("owner", "Sir Eric Parker");
DBObject update = new BasicDBObject();
update.put("$set", set);
collection.update(query, update);
}
view raw isudupdate.java hosted with ❤ by GitHub

Please refer to Updating a document using the default ObjectId for the reasoning behind DBObjectFactory


The DELETE of CRUD
Finally, we can delete a document.

...this is how you would do it from the mongo shell...
db.stuff.delete({"name" : "Seagram"})
view raw isuddeleteshell hosted with ❤ by GitHub

...and the Java implementation...
//assume parameter 'name' is passed to the method
try {
Mongo mongo = new Mongo("localhost" , 27017);
DB db = mongo.getDB( "isud" );
DBCollection collection = db.getCollection("stuff");
DBObject query = new BasicDBObject();
query.put("name", name);
collection.remove(query);
}
view raw isuddelete.java hosted with ❤ by GitHub

It's all relatively straight forward really. Though none of this is rocket science, I for one find this a useful and succinct reminder or as previously stated; a hinting mechanism.

1 comment:

  1. I just wanted to make one point clear regarding the update secition of this post. The api docs (http://api.mongodb.org/java/current/) state save(DBObject jo) "Saves an object to this collection (does insert or update based on the object _id).". This is actually a remove and replace, which is confirmed here (http://article.gmane.org/gmane.comp.db.mongodb.user/56566) IMHO this is a misnomer and is misleading, to me anyway.

    More often than not I use findAndModify. Why? Because more often than not I want to have control over which fields are subsequently returned.

    ReplyDelete