MongoDB Java tutorial

In this tutorial, we show how to work with MongoDB in Java. There is a concise Java tutorial on ZetCode.

MongoDB is a NoSQL cross-platform document-oriented database. It is one of the most popular databases available. MongoDB is developed by MongoDB Inc. and is published as free and open-source software.

A record in MongoDB is a document, which is a data structure composed of field and value pairs. MongoDB documents are similar to JSON objects. The values of fields may include other documents, arrays, and arrays of documents. MongoDB stores documents in collections. Collections are analogous to tables in relational databases and documents to rows.

Installing MongoDB

The following command can be used to install MongoDB on a Debian-based Linux.

$ sudo apt-get install mongodb

The command installs the necessary packages that come with MongoDB.

$ sudo service mongodb status
mongodb start/running, process 975

With the sudo service mongodb status command we check the status of the mongodb server.

$ sudo service mongodb start
mongodb start/running, process 6448

The mongodb server is started with the sudo service mongodb start command.

Creating a database

The mongo tool is an interactive JavaScript shell interface to MongoDB, which provides an interface for systems administrators as well as a way for developers to test queries and operations directly with the database.

$ mongo testdb
MongoDB shell version: 2.4.9
connecting to: testdb
> db
testdb
> db.cars.insert({name: "Audi", price: 52642})
> db.cars.insert({name: "Mercedes", price: 57127})
> db.cars.insert({name: "Skoda", price: 9000})
> db.cars.insert({name: "Volvo", price: 29000})
> db.cars.insert({name: "Bentley", price: 350000})
> db.cars.insert({name: "Citroen", price: 21000})
> db.cars.insert({name: "Hummer", price: 41400})
> db.cars.insert({name: "Volkswagen", price: 21600})

We create a testdb database and insert eight documents in the cars collection.

Installing Java driver

We use the following Maven declaration to include the MongoDB Java driver in our project.

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongo-java-driver</artifactId>
    <version>x.y.z</version>
</dependency>

It is an all-in-one JAR, which embeds the core driver and BSON. BSON, short for Bin­ary JSON, is a bin­ary-en­coded seri­al­iz­a­tion of JSON-like doc­u­ments.

Listing database collections

The first example connects to the testdb database and retrieves its collections.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zetcode</groupId>
    <artifactId>MongoListCollections</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>org.mongodb</groupId>
            <artifactId>mongo-java-driver</artifactId>
            <version>3.0.4</version>
        </dependency>
    </dependencies>        
</project>

This is our pom.xml file.

MongoListCollections.java
package com.zetcode;

import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;

public class MongoListCollections {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        for (String name : database.listCollectionNames()) {
            
            System.out.println(name);
        }

        mongoClient.close();
    }
}

The example connects to the testdb database and retrieves all its collections.

MongoClient mongoClient = new MongoClient("localhost", 27017);

The MongoClient class is used to connect to the MongoDB server. The 27017 is the default port on which the MongoDB server listens.

MongoDatabase database = mongoClient.getDatabase("testdb");

With the getDatabase() method, we retrieve the testdb database.

for (String name : database.listCollectionNames()) {
    
    System.out.println(name);
}

The listCollectionNames() method finds all the collections in the testdb database.

mongoClient.close();

Finally, the close() method releases all resources associated with this instance of MongoClient.

system.indexes
cars

In our database, we have these two collections.

Database statistics

The next example connects to the testdb database and gets its statistics.

MongoCommand.java
package com.zetcode;

import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import java.util.Map;

public class MongoCommand {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        Document stats = database.runCommand(new Document("dbstats", 1));

        for (Map.Entry<String, Object> set : stats.entrySet()) {
                       
            System.out.format("%s: %s%n", set.getKey(), set.getValue());
        }

        mongoClient.close();
    }
}

The example connects to the testdb database and executes the dbstats command. It shows some database statistics.

Document stats = database.runCommand(new Document("dbstats", 1));

With the runCommand() method, we execute the dbstats command. The command returns a Document, which is a representation of a MongoDB document as a map.

for (Map.Entry<String, Object> set : stats.entrySet()) {
                
    System.out.format("%s: %s%n", set.getKey(), set.getValue());
}

We iterate through the entries of the document.

db: testdb
collections: 3
objects: 13
avgObjSize: 47.38461538461539
dataSize: 616
storageSize: 16384
numExtents: 3
indexes: 1
indexSize: 8176
fileSize: 201326592
nsSizeMB: 16
dataFileVersion: Document{{major=4, minor=5}}
ok: 1.0

This is the output of the example.

Reading data

MongoCollection is used to store mongo documents returned from a collection. MongoCursor is a cursor to iterate through the results of a database query. It makes sure that it is closed in case of an exception.

MongoReadAll.java
package com.zetcode;

import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import java.util.ArrayList;
import java.util.List;

public class MongoReadAll {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> col = database.getCollection("cars");

        try (MongoCursor<Document> cur = col.find().iterator()) {
            while (cur.hasNext()) {

                Document doc = cur.next();
                
                List list = new ArrayList(doc.values());
                System.out.print(list.get(1));
                System.out.print(": ");
                System.out.println(list.get(2));
            }
        }

        mongoClient.close();
    }
}

In the example, we iterate over all data of the cars collection.

MongoCollection<Document> col = database.getCollection("cars");

We retrieve the cars collection with the getCollection() method.

try (MongoCursor<Document> cur = col.find().iterator()) {
    while (cur.hasNext()) {

        Document doc = cur.next();
        
        List list = new ArrayList(doc.values());
        System.out.print(list.get(1));
        System.out.print(": ");
        System.out.println(list.get(2));
    }
}

We iterate through the documents of the collection. The find() method finds all documents in the collection.

Audi: 52642
Mercedes: 57127
Skoda: 9000
Volvo: 29000
Bentley: 350000
Citroen: 21000
Hummer: 41400
Volkswagen: 21600

This is the output of the example.

Query operators

It is possible to filter the data using MongoDB query operators such as $gt, $lt, or $ne. The query operators can be specified in the BasicDBObject class.

MongoReadGreaterThan.java
package com.zetcode;

import com.mongodb.BasicDBObject;
import com.mongodb.Block;
import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class MongoReadGreaterThan {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> col = database.getCollection("cars");

        BasicDBObject query = new BasicDBObject("price", 
                new BasicDBObject("$gt", 30000));
       
        col.find(query).forEach(new Block<Document>() {
            @Override
            public void apply(final Document document) {
                System.out.println(document.toJson());
            }
        });       
        
        mongoClient.close();
    }
}

The example prints all documents whose car prices' are greater than 30,000.

BasicDBObject query = new BasicDBObject("price", 
        new BasicDBObject("$gt", 30000));

We use the $gt query operator.

col.find(query).forEach(new Block<Document>() {
    @Override
    public void apply(final Document document) {
        System.out.println(document.toJson());
    }
});  

The forEach() method is a syntactic sugar to avoid the need for the application code to worry about having to close the cursor manually. The data is printed in the JSON format using the toJson() method.

{ "_id" : 1, "name" : "Audi", "price" : 52642 }
{ "_id" : 2, "name" : "Mercedes", "price" : 57127 }
{ "_id" : 5, "name" : "Bentley", "price" : 350000 }
{ "_id" : 7, "name" : "Hummer", "price" : 41400 }

This is the output of the example in the JSON format. Only cars more expensive than 30,000 are included.

Factory filter query methods

The Java MongoDB driver contains factory methods for query filters.

MongoFilter.java
package com.zetcode;

import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.gt;
import static com.mongodb.client.model.Filters.lt;
import java.util.ArrayList;

public class MongoFilter {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> col = database.getCollection("cars");
               
        FindIterable it = col.find(and(lt("price", 50000),
                gt("price", 20000))).sort(new Document("price", -1));
        
        ArrayList<Document> docs = new ArrayList();
        
        it.into(docs);

        for (Document doc : docs) {
            System.out.println(doc);
        }
        
        mongoClient.close();
    }
}

In the example, we retrieve cars whose prices fall between 20,000 and 50,000.

FindIterable it = col.find(and(lt("price", 50000),
        gt("price", 20000))).sort(new Document("price", -1));

The and(), gt(), and lt() are factory filter methods. In addition, the data is sorted with the sort() method.

Document{{_id=7, name=Hummer, price=41400}}
Document{{_id=4, name=Volvo, price=29000}}
Document{{_id=8, name=Volkswagen, price=21600}}
Document{{_id=6, name=Citroen, price=21000}}

This is the output of the example.

Projections

The Projections class provides static factory methods for all the MongoDB projection operators. By default, all fields of each document are projected. We can use the include and exclude() methods to determine which fields should be projected into our output.

MongoProjection.java
package com.zetcode;

import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import static com.mongodb.client.model.Projections.excludeId;
import java.util.ArrayList;

public class MongoProjection {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> contCol = database.getCollection("cars");
        
        FindIterable it = contCol.find().projection(excludeId());
        
        ArrayList<Document> docs = new ArrayList();
        
        it.into(docs);

        for (Document doc : docs) {
            System.out.println(doc);
        }        
               
        mongoClient.close();
    }
}

The example excludes the _id field from the output.

FindIterable it = contCol.find().projection(excludeId());

The projection() method sets a document describing the fields to return for all matching documents. The excludeId() is a synonym for exclude("_id").

Document{{name=Audi, price=52642}}
Document{{name=Mercedes, price=57127}}
Document{{name=Skoda, price=9000}}
Document{{name=Volvo, price=29000}}
Document{{name=Bentley, price=350000}}
Document{{name=Citroen, price=21000}}
Document{{name=Hummer, price=41400}}
Document{{name=Volkswagen, price=21600}}

This is the output for the example.

Limiting data output

The limit query option specifies the number of documents to be returned and the sort option the sort order.

MongoSkipLimit.java
package com.zetcode;

import com.mongodb.Block;
import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

public class MongoSkipLimit {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> col = database.getCollection("cars");

        FindIterable it = col.find().skip(2).limit(5);
        
        it.forEach((Block<Document>) System.out::println);
        
        mongoClient.close();
    }
}

The example reads from the testdb.cars collection, skips the first two documents, and limits the output to five documents.

FindIterable it = col.find().skip(2).limit(5);

The FindIterable's skip() method skips the first two documents and the limit() method limits the output to five documents.

it.forEach((Block<Document>) System.out::println);

Here we use Java 8 construct to print the documents.

Document{{_id=3, name=Skoda, price=9000}}
Document{{_id=4, name=Volvo, price=29000}}
Document{{_id=5, name=Bentley, price=350000}}
Document{{_id=6, name=Citroen, price=21000}}
Document{{_id=7, name=Hummer, price=41400}}

This is the output of the example.

Creating a collection

The MongoDatabase's createCollection() method creates a new collection in the database. The MongoCollection's insertMany() method inserts one or more documents into the collection.

MongoCreateCollection.java
package com.zetcode;

import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.MongoCommandException;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import java.util.ArrayList;
import java.util.List;

public class MongoCreateCollection {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");
        
        try {

            database.createCollection("cars");
        } catch (MongoCommandException e) {

            database.getCollection("cars").drop();
        } 

        List<Document> writes = new ArrayList<>();

        MongoCollection<Document> carsCol = database.getCollection("cars");

        Document d1 = new Document("_id", 1);
        d1.append("name", "Audi");
        d1.append("price", 52642);
        writes.add(d1);

        Document d2 = new Document("_id", 2);
        d2.append("name", "Mercedes");
        d2.append("price", 57127);
        writes.add(d2);

        Document d3 = new Document("_id", 3);
        d3.append("name", "Skoda");
        d3.append("price", 9000);
        writes.add(d3);

        Document d4 = new Document("_id", 4);
        d4.append("name", "Volvo");
        d4.append("price", 29000);
        writes.add(d4);

        Document d5 = new Document("_id", 5);
        d5.append("name", "Bentley");
        d5.append("price", 350000);
        writes.add(d5);

        Document d6 = new Document("_id", 6);
        d6.append("name", "Citroen");
        d6.append("price", 21000);
        writes.add(d6);

        Document d7 = new Document("_id", 7);
        d7.append("name", "Hummer");
        d7.append("price", 41400);
        writes.add(d7);

        Document d8 = new Document("_id", 8);
        d8.append("name", "Volkswagen");
        d8.append("price", 21600);
        writes.add(d8);

        carsCol.insertMany(writes);

        mongoClient.close();
    }
}

The example creates a cars collection and inserts nine documents into it.

try {

    database.createCollection("cars");
} catch (MongoCommandException e) {

    database.getCollection("cars").drop();
} 

A new collection is created with the createCollection() method. If the collection already exists, it is dropped.

MongoCollection<Document> carsCol = database.getCollection("cars");

A MongoCollection of documents is created with the getCollection() method.

Document d1 = new Document("_id", 1);
d1.append("name", "Audi");
d1.append("price", 52642);
writes.add(d1);

A new Document is created. It contains the information about the car—its ID, name, and price.

carsCol.insertMany(writes);

The documents are written to the collection with the insertMany() method.

Creating a collection from JSON

The JSON class has methods for parsing JSON documents. JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write.

MongoCollectionFromJSON.java
package com.zetcode;

import com.mongodb.BasicDBObject;
import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.util.JSON;

public class MongoCollectionFromJSON {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> contCol = database.getCollection("continents");
        
        BasicDBObject africa = (BasicDBObject) JSON.parse("{_id : 1, name : 'Africa'}");
        BasicDBObject asia = (BasicDBObject) JSON.parse("{_id : 2, name : 'Asia'}");
        BasicDBObject europe = (BasicDBObject) JSON.parse("{_id : 3, name : 'Europe'}");
        BasicDBObject america = (BasicDBObject) JSON.parse("{_id : 4, name : 'America'}");
        BasicDBObject australia = (BasicDBObject) JSON.parse("{_id : 6, name : 'Australia'}");
        BasicDBObject antarctica = (BasicDBObject) JSON.parse("{_id : 7, name : 'Antarctica'}");
        
        contCol.insertOne(new Document(africa));
        contCol.insertOne(new Document(asia));
        contCol.insertOne(new Document(europe));
        contCol.insertOne(new Document(america));
        contCol.insertOne(new Document(australia));
        contCol.insertOne(new Document(antarctica));
        
        mongoClient.close();
    }
}

The example creates a continents collection from JSON data.

BasicDBObject africa = (BasicDBObject) JSON.parse("{_id : 1, name : 'Africa'}");

JSON data is parsed with the JSON.parse() method. Then it is cast to BasicDBObject.

contCol.insertOne(new Document(africa));

The BasicDBObject is passed to Document and inserted into the collection with the insertOne() method.

> db.continents.find()
{ "_id" : 1, "name" : "Africa" }
{ "_id" : 2, "name" : "Asia" }
{ "_id" : 3, "name" : "Europe" }
{ "_id" : 4, "name" : "America" }
{ "_id" : 6, "name" : "Australia" }
{ "_id" : 7, "name" : "Antarctica" }

We show the created collection with mongo.

Modifying documents

The MongoCollection's deleteOne() method is used to delete a document and updateOne() to update a document.

MongoModify.java
package com.zetcode;

import org.bson.Document;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import static com.mongodb.client.model.Filters.eq;

public class MongoModify {

    public static void main(String[] args) {

        MongoClient mongoClient = new MongoClient("localhost", 27017);
        MongoDatabase database = mongoClient.getDatabase("testdb");

        MongoCollection<Document> col = database.getCollection("cars");
        
        col.deleteOne(eq("name", "Skoda"));
        col.updateOne(new Document("name", "Audi"),  
                new Document("$set", new Document("price", 52000)));

        mongoClient.close();
    }
}

The example deletes a document containing Skoda and updates the price of Audi.

col.deleteOne(eq("name", "Skoda"));

The deleteOne() deletes the document of Skoda. The eq() creates a filter that matches all documents where the value of the field name equals the specified value.

col.updateOne(new Document("name", "Audi"),  
        new Document("$set", new Document("price", 52000)));

The price of Audi is changed to 52,000 with the updateOne() method.

> db.cars.find()
{ "_id" : 1, "name" : "Audi", "price" : 52000 }
{ "_id" : 2, "name" : "Mercedes", "price" : 57127 }
{ "_id" : 4, "name" : "Volvo", "price" : 29000 }
{ "_id" : 5, "name" : "Bentley", "price" : 350000 }
{ "_id" : 6, "name" : "Citroen", "price" : 21000 }
{ "_id" : 7, "name" : "Hummer", "price" : 41400 }
{ "_id" : 8, "name" : "Volkswagen", "price" : 21600 }

We confirm the changes with the mongo tool.

In this tutorial, we have worked with MongoDB and Java. You might be also interested in MySQL Java tutorial or PostgreSQL Java tutorial.