Java Quiz Player

A CRUD App with MongoDB Java

October 2, 2020

1. Overview

This is an example Java application with a command-line user interface to perform CRUD operations (Create Read Update Delete) on MongoDB database.

MongoDB is a NoSQL document based database. Data is stored in databases, collections and documents. These are analogous to database, table and row in SQL and tabular database system. The document data is similar to JSON in structure, with fields defined as key value pairs. The data stored in the database is BSON (binary JSON) types. These are an extension to JSON which provide additional data types like date, various numeric types, etc., in addition to the JSON string, boolean, number, array and object types.

The standard way to connect to the MongoDB server is from a client application. mongo shell, the command-line tool is included with the database, is commonly used to perform administrative and data related tasks. A client can also be an application developed using a programming language like Java, Python or NodeJS platform. The client program connects to the database server via a driver. For Java applications it is the MongoDB Java Driver. In addition to connection, the driver also converts the data from the client format to the BSON stored on the database server, and vice-versa.

This application is command-line program, runs from the OS terminal. It has a menu as shown in the screenshot below. The user can select an option to perform a task - a CRUD operation. The user can enter data interactively and get the result of the database operation.

GUI image

The application is written using Java SE 8 and MongoDB Java Driver v3.12.2. The app connects to MongoDB Server v4.2.8. The code runs from the terminal or from an IDE like IntelliJ Idea.

The Java source code for the application can be downloaded from the Download section below.

2. The mongo Shell

mongo shell is an interactive command-line tool included with an installation of the MongoDB. You can connect to the server by typing:

> mongo

This connects to the server and shell interface allows the database operations. By default, the shell connects to MongoDB running on localhost with port 27017. You can also specify these options when starting the shell.

Here are some basic commands (Note the shell use JavaScript syntax):

> show dbs
test
blog

> show collections
persons
sales
testColl

> db
test

> use crud
switched to db crud

> var doc = { name: "John", city: "New York" }

> db.names.insertOne(doc);
{
        "acknowledged" : true,
        "insertedId" : ObjectId("5f6cac04d35a6397ae971f18")
}

> db.names.find()
{ "_id" : ObjectId("5f6cac04d35a6397ae971f18"), "name" : "John", "city" : "New York" }

The above code (or commands) lists all the databases, lists all the collections in the current database, shows what the current database is, makes a database current, creates a JSON document and assigns it to a variable, inserts the JSON into a collection and queries the collection.

In the above code, the crud database and names collection are created newly with the insert command. When the first document is inserted into a collection, the database and collection are created, if they do not already exist.

The updateOne and deleteOne commands are used to update and delete a document from the collection. The find, update and delete take a filter as an argument to target a specific document. There are variations of these methods to work with multiple documents (e.g., insertMany).

Note the field _id from the result of the find query. It is created by the driver and is of type ObjectId. It is assigned to the newly inserted document. This field acts as a primary key. It is a mandatory field for each document in a collection, has a unique index defined on it and is immutable. You can provide your own _id field's value, and this can be any BSON type except an array; e.g., timestamp, string.

3. CRUD with Java

The example uses a database named crud and a collection named names. Each document in the collection has two fields - name and city. Then there is the mandatory _id field. The app's user will supply the name and city field values and the _id field is system generated. An example document:

{ 
  "_id" : ObjectId("5f6cac04d35a6397ae971f18"), 
  "name" : "John", 
  "city" : "New York" 
}

The app's MongoOps.java class has all the database related operations: create a connection, insert, update, delete a document, query all documents and finally query by the two fields or a single field.

3.1. Database Connection

The following code creates a connection to the database and gets an instance of collection. We will apply CRUD methods on this collection object.

final String CONNECTION_URL = "mongodb://localhost:27017/";
MongoClient mongoClient = MongoClients.create(CONNECTION_URL);
MongoCollection<Document> collection = mongoClient.getDatabase("crud")
                                                  .getCollection("names");

3.2. Insert Document

The app's create function adds a document for a given name and city. In case the user doesn't provide any or both the values, the program will pick a random name and/or city from an array of few values. The document creation code using the user supplied field values:

Document doc = new Document("name", name).append("city", city);
collection.insertOne(doc);

3.3. Update Document

The update function updates the city field value for a given name. The update happens using the user supplied field values. The update method takes a filter to find the document with the matching name and applies the update on the city field:

Bson filter = Filters.eq("name", name);
Bson update = Updates.set("city", city);
UpdateResult result = collection.updateOne(filter, update);

3.4. Delete Document

The delete operation lets user specify the name field and the corresponding document is deleted from the collection.

Bson filter = new Document().append("name", name);
DeleteResult result = collection.deleteOne(filter);

3.5. Query Collection

There are two query functions.

The "query all" gets all the documents from the collection and collects them in a List<Document>:

return collection.find().into(new ArrayList<Document>());

Here is the screenshot showing the query result. Note the "_id": {"$oid": "5f6ee6ab4bf05b07430c5193"} is the JSON representation of ObjectId("5f6ee6ab4bf05b07430c5193").

GUI image

Then there is a query by field - name and/or city. In this case a filter is applied specifying the condition. The specific name and/or city are provided by the user.

The query uses one of the following three filters, depending on the user input:
Bson filter = Filters.eq("city", city);
Bson filter = Filters.eq("name", name);
Bson filter = Filters.and(Filters.eq("name", name), Filters.eq("city", city));
The query with the filter:
return collection.find(filter).into(new ArrayList<Document>());

3.6. Other Database Operations

Though not included in this app's functionality, here are some database administrative commands:

MongoClient#listDatabases()
MongoDatabase#drop()
MongoDatabase#createCollection()
MongoCollection#countDocuments()
MongoDatabase#runCommand()

The above commands explain themselves. Note that all are instance methods. The runCommand() allows run the native MongoDB commands from your Java application. For example, database.runCommand(new Document("drop", "testdb"));, drops the specified database.

4. Notable Features

MongoDB also has these features out of the box: Transactions, Change Streams (access real-time data changes), Replication (data redundancy and high availability using multiple servers) and Sharding (data distribution across multiple servers).

An important feature of MongoDB document structure is its flexible schema. For example, you can include a new field into a document without any new definitions. Consider the code from the mongo shell:

> db.names.insertOne( 
    { name: "Kim", city: "Seoul", favorites: [ "apples", "red", "sailing" ] } 
  )

This code snippet inserts a new document into the names collection with the new array field favorites. Now the collection has documents with different fields. For stricter validation of document structure you can use the Schema Validation feature for insert and update operations.

5. The Example Application

The Main.java launches the app. This class uses a java.util.Scanner to accept user input from command-line. The input is validated, processed and the result is shown on the terminal. All the database operations are performed in the MongoOps.java class.

The MongoDB database access code uses the MongoDB Java driver. By default this driver logs using a logger. This app is a command-line program and the detailed logging interferes with the app's functionality (reading from the terminal and writing to it). So, the logging is suppressed by setting the logging level to LEVEL.SEVERE from the default INFO.

The insert, update and delete database operation Java methods may throw a runtime exception, the MongoException due to an error during an operation. In such a case the application prints an appropriate message and exits. There is also a properties file with the MongoDB connection host and port information. The propreties are loaded from the AppProperties.java class.

Browse the Java source code:

6. Download

Download the Java source code for the example: mongo-java-crud-app.zip

7. Useful Links

Return to top