





















































In this article by Francesco Marchioni, author of the book MongoDB for Java Developers, you will be able to perform all the create/read/update/delete (CRUD) operations that we have so far accomplished using the mongo shell.
(For more resources related to this topic, see here.)
We will now see how to use the Java API to query for your documents. Querying for documents with MongoDB resembles JDBC queries; the main difference is that the returned object is a com.mongodb.DBCursor class, which is an iterator over the database result.
In the following example, we are iterating over the javastuff collection that should contain the documents inserted so far:
package com.packtpub.mongo.chapter2; import com.mongodb.DB; import com.mongodb.DBCollection; import com.mongodb.DBCursor; import com.mongodb.DBObject; import com.mongodb.MongoClient; public class SampleQuery{ private final static String HOST = "localhost"; private final static int PORT = 27017; public static void main( String args[] ){ try{ MongoClient mongoClient = new MongoClient( HOST,PORT ); DB db = mongoClient.getDB( "sampledb" ); DBCollection coll = db.getCollection("javastuff"); DBCursor cursor = coll.find(); try { while(cursor.hasNext()) { DBObject object = cursor.next(); System.out.println(object); } } finally { cursor.close(); } } catch(Exception e) { System.err.println( e.getClass().getName() + ": " + e.getMessage() ); } } }
Depending on the documents you have inserted, the output could be something like this:
{ "_id" : { "$oid" : "5513f8836c0df1301685315b"} , "name" : "john" ,
"age" : 35 , "kids" : [ { "name" : "mike"} , { "name" : "faye"}] ,
"info" : { "email" : "[email protected]" , "phone" : "876-134-667"}} . . . .
The find operator executed without any parameter returns the full cursor of a collection; pretty much like the SELECT * query in relational DB terms. If you are interested in reading just the first document in the collection, you could use the findOne() operation to get the first document in the collection. This method returns a single document (instead of the DBCursor that the find() operation returns). As you can see, the findOne() operator directly returns a DBObject instead of a com.mongodb.DBCursor class:
DBObject myDoc = coll.findOne(); System.out.println(myDoc);
Another typical construct that you probably know from the SQL is the SELECT count(*) query that is useful to retrieve the number of records in a table. In MongoDB terms, you can get this value simply by invoking the getCount against a DBCollection class:
DBCollection coll = db.getCollection("javastuff"); System.out.println(coll.getCount());
As an alternative, you could execute the count() method over the DBCursor object:
DBCursor cursor = coll.find(); System.out.println(cursor.count());
When find is executed and a DBCursor is executed you have a pointer to a database document. This means that the documents are fetched in the memory as you call next() method on the DBCursor.
On the other hand, you can eagerly load all the data into the memory by executing the toArray() method, which returns a java.util.List structure:
List list = collection.find( query ).toArray();
The problem with this approach is that you could potentially fill up the memory with lots of documents, which are eagerly loaded. You are therefore advised to include some operators such as skip() and limit() to control the amount of data to be loaded into the memory:
List list = collection.find( query ).skip( 100 ). limit( 10 ).toArray();
Just like you learned from the mongo shell, the skip operator can be used as an initial offset of your cursor whilst the limit construct can eventually load the first n occurrences in the cursor.
Typically, you will not need to fetch the whole set of documents in a collection. So, just like SQL uses WHERE conditions to filter records, in MongoDB you can restrict searches by creating a BasicDBObject and passing it to the find function as an argument. See the following example:
DBCollection coll = db.getCollection("javastuff"); DBObject query = new BasicDBObject("name", "owen"); DBCursor cursor = coll.find(query); try { while(cursor.hasNext()) { System.out.println(cursor.next()); } } finally { cursor.close(); }
In the preceding example, we retrieve the documents in the javastuff collection, whose name key equals to owen. That's the equivalent of an SQL query like this:
SELECT * FROM javastuff WHERE name='owen'
As your collections keep growing, you will need to be more selective with your searches. For example, you could include multiple keys in your BasicDBObject that will eventually be passed to find. We can then apply the same functions in our queries. For example, here is how to find documents whose name does not equal ($ne) to Frank and whose age is greater than 10:
DBCollection coll = db.getCollection("javastuff"); DBObject query = new BasicDBObject("name", new BasicDBObject("$ne", "frank")).append("age", new BasicDBObject("$gt", 10)); DBCursor cursor = coll.find(query);
Having learned about create and read, we are half way through our CRUD track. The next operation you will learn is update. The DBCollection class contains an update method that can be used for this purpose. Let's say we have the following document:
> db.javastuff.find({"name":"frank"}).pretty() { "_id" : ObjectId("55142c27627b27560bd365b1"), "name" : "frank", "age" : 31, "info" : { "email" : "[email protected]", "phone" : "222-111-444" } }
Now we want to change the age value for this document by setting it to 23:
DBCollection coll = db.getCollection("javastuff"); DBObject newDocument = new BasicDBObject(); newDocument.put("age", 23); DBObject searchQuery = new BasicDBObject().append("name", "owen"); coll.update(searchQuery, newDocument);
You might think that would do the trick, but wait! Let's have a look at our document using the mongo shell:
> db.javastuff.find({"age":23}).pretty() { "_id" : ObjectId("55142c27627b27560bd365b1"), "age" : 23 }
As you can see, the update statement has replaced the original document with another one, including only the keys and values we have passed to the update. In most cases, this is not what we want to achieve. If we want to update a particular value, we have to use the $set update modifier.
DBCollection coll = db.getCollection("javastuff"); BasicDBObject newDocument = new BasicDBObject(); newDocument.append("$set", new BasicDBObject().append("age", 23)); BasicDBObject searchQuery = new BasicDBObject().append("name", "frank"); coll.update(searchQuery, newDocument);
So, suppose we restored the initial document with all the fields, this is the outcome of the update using the $set update modifier:
> db.javastuff.find({"age":23}).pretty() { "_id" : ObjectId("5514326e627b383428c2ccd8"), "name" : "frank", "age" : 23, "in,fo" : { "email" : "[email protected]", "phone" : "222-111-444" } }
Please note that the DBCollection class overloads the method update with update (DBObject q, DBObject o, boolean upsert, boolean multi). The first parameter (upsert) determines whether the database should create the element if it does not exist. The second one (multi) causes the update to be applied to all matching objects.
The operator to be used for deleting documents is obviously delete. As for other operators, it includes several variants. In its simplest form, when executed over a single document returned, it will remove it:
MongoClient mongoClient = new MongoClient("localhost", 27017); DB db = mongoClient.getDB("sampledb"); DBCollection coll = db.getCollection("javastuff"); DBObject doc = coll.findOne(); coll.remove(doc);
Most of the time you will need to filter the documents to be deleted. Here is how to delete the document with the key frank:
DBObject document = new BasicDBObject(); document.put("name", "frank"); coll.remove(document);
Bulk deletion of documents can be achieved by including the keys in a List and building an $in modifier expression that uses this list. Let's see, for example, how to delete all records whose age ranges from 0 to 49:
BasicDBObject deleteQuery = new BasicDBObject(); List<Integer> list = new ArrayList<Integer>(); for (int i=0;i<50;i++) list.add(i); deleteQuery.put("age", new BasicDBObject("$in", list));
In this article, we covered how to perform the same operations that are available in the mongo shell.
Further resources on this subject: