A Guide to MongoDB With Java

1. Overview

In this article, we’ll have a look at integrating MongoDB, a very popular NoSQL database with a standalone Java client application.

MongoDB is a distributed database at its core, which means high availability, horizontal scaling, and geographic distribution are built-in and easy to use.

2. MongoDB Concepts and Terminology

Let’s start with a few key points about MongoDB itself.

MongoDB stores data as a document, which is a data structure composed of field and value pairs. MongoDB documents look similar to JSON objects. The values of fields can be scalar values, such as strings and numbers, but may include other documents, arrays, and arrays of documents. This allows for more complex data models to represent our data.

The advantages of using documents include:

  • Documents correspond to native data types in many programming languages
  • Embedded documents and arrays reduce the need for expensive joins
  • Dynamic schema supports fluent polymorphism

We can also compare traditional relational database terms with their MongoDB equivalents:

  • Table in relational databases becomes Collection in MongoDB
  • Row becomes Document
  • Column becomes Field
  • Joins are achieved through embedded documents, document references, or $lookup to combine data from different collections

This is a simplified but useful way to look at the MongoDB core concepts.

Now, let’s look into a sample implementation to understand the MongoDB database.

3. Using MongoDB

Throughout this tutorial, we’ll be connecting to an external MongoDB server. To set up our own free cluster, we head to MongoDB Atlas cluster and follow the steps to get a database hosted in the cloud.

Next, we’ll connect to our MongoDB database, and run some CRUD operations against it.

3.1. Maven Dependency

We’ll be using the mongodb-driver-sync Java Driver for MongoDB:

<dependency>
    <groupId>org.mongodb</groupId>
    <artifactId>mongodb-driver-sync</artifactId>
    <version>5.0.1</version>
</dependency>Copy

This driver is suited for synchronous Java applications that make blocking calls to the MongoDB database. MongoDB also has a Java Reactive Streams Driver for asynchronous applications.

3.2. Make a Connection With MongoClient

First, let’s make a connection to our MongoDB server. We’ll use the MongoClient:

String uri = "mongodb+srv://user:password@cluster.example.mongodb.net/";
MongoClient mongoClient = MongoClients.create(uri)Copy

This uri example follows the same format we can expect our connection string to resemble.

3.3. Connecting to a Database

After that, let’s connect to our database. When we specify a database to use, if no database of that name exists, MongoDB creates it upon the first write operation.

For this, we’ll use the sample_mflix database MongoDB provides, which comes loaded with several sample collections already:

MongoDatabase database = mongoClient.getDatabase("sample_mflix");Copy

To connect to another database, we just specify the name in place of our database sample_mflix.

3.4. Create a Collection

Additionally, if we wanted to create a collection (table equivalent for MongoDB) in the code, we use:

database.createCollection("movies");Copy

This creates a collection called movies in our database, if one doesn’t exist already.

3.5. Inserting Documents

We can insert a single document into a collection using the insertOne() method on a MongoCollection object, or multiple documents using the insertMany() method.

To insert a document, we construct a Document object with the fields and values that we want to store. If we call the insertOne() method on a collection that doesn’t exist yet, the server automatically creates it for us.

Let’s insert a new movie Document into our movies collection collection:

MongoDatabase database = mongoClient.getDatabase("sample_mflix");
MongoCollection<Document> collection = database.getCollection("movies");

collection.insertOne(new Document()
  .append("_id", new ObjectId())
  .append("title", "Silly Video")
  .append("genres", Arrays.asList("Action", "Adventure")));Copy

We create a Document object and add a title field with a string value, and a genres field with a List<String> values.

We also add an _id field. In MongoDB, every document needs an immutable _id value, which we’re initializing using an ObjectId object. Each ObjectId is unique by design. While we can technically use any value we can expect to never change, such as the title, it can be difficult to guarantee uniqueness, and so often using a unique random value is the way to go.

The entity will be sent data to MongoDB and stored as BSON (Binary JSON), which is faster compared to JSON itself when it comes to querying the data:

{
  "_id": {
    "$oid": "662117c69611c5728c351ebf"
  },
  "title": "Silly Video",
  "genres": [
    "Action",
    "Adventure"
  ]
}Copy

To insert multiple documents at the same time, we can use the insertMany() method:

List<Document> movieList = Arrays.asList(
  new Document().append("title", "Silly Video 2"),
  new Document().append("title", "Silly Video: The Prequel"));

InsertManyResult result = collection.insertMany(movieList);Copy

This takes in our array of JSON documents and send these to MongoDB to be stored as individual documents.

3.6. Finding Documents

We can retrieve a single document from a collection by using the find() and first() methods.

A simple find operation might look like this:

collection.find(eq("title", "The Great Train Robbery"))
  .first();Copy

A query filter is passed to the find() method. The eq() filter matches only movies with the exact title “The Great Train Robbery”. This returns the rather large document in our database, and if there are multiple with that title, there is no guarantee it’s the document we want. We can refine our results using various methods, all of which we can find in the MongoDB docs.

For example, let’s do a search:

Bson projectionFields = Projections.fields(
  Projections.include("title", "genres"),
  Projections.excludeId());

collection.find(eq("title", "The Great Train Robbery"))
  .projection(projectionFields)
  .sort(Sorts.ascending("year"))
  .first();Copy

There are a couple of new steps to our find() operation:

  • sort() that organises matched documents in ascending order by year. Pairing this with the first() method allows us to return only the oldest movie with the matching title.
  • projection() that includes the objects in the title and genre fields and excludes the _id field using the helper method excludeId().

We can query for multiple documents using the find() method in much the same way, but how we access and traverse the results is slightly different.

Let’s create a query which finds all documents with a year greater than 1900 and sort them from oldest to newest, then limit the fields projected to just the title and year of each document returned.

Bson projectionFields = Projections.fields(
  Projections.include("title", "year"),
  Projections.excludeId());

MongoCursor<Document> cursor = collection.find(gt("year", 1900))
  .projection(projectionFields)
  .sort(Sorts.asscending("title")).iterator();Copy

We call the iterator() method which returns a MongoCursor instance. We use it to traverse the results.

A cursor is just a mechanism that allows us to iterate over our database results while only holding a subset in memory at any given time.

MongoCursor has methods such as hasNext() to check whether additional results exist, or next() to return the next document in the collection. If no documents match the query, calling hasNext() returns false and therefore calling next() throws an exception. So we always use hasNext() to verify there is another document first.

This means if we wanted to print the results of the find() operation, we could do something like this:

try {
    while (cursor.hasNext()) {
        logger.info(cursor.next().toJson());
    }
} finally {
    cursor.close();
}Copy

This parses through the values in our cursor and display our documents.

3.7. Updating Documents

Now let’s look at how we can update our documents in our MongoDB database. We’ll start with just one document using the updateOne() method.

Let’s update the document we added earlier:

Document updateQuery = new Document().append("title", "Silly Video");

Bson updates = Updates.combine(
  Updates.set("runtime", 99),
  Updates.addToSet("genres", "Comedy")
  Updates.currentTimestamp("lastUpdated"));

collection.updateOne(updateQuery, updates);
Copy

This sets the runtime of our document to 99, and add the value Comedy to the genres array. It also adds a field for lastUpdated, automatically populated with the current timestamp, which is a good idea for auditing our database and tracking changes in data.

To update many documents, the updateMany() method takes the query filter and updates all the documents that match:

Bson query = gt("num_mflix_comments", 50);

Bson updates = Updates.combine(
  Updates.addToSet("genres", "Frequently Discussed"),
  Updates.currentTimestamp("lastUpdated"));

collection.updateMany(query, updates);Copy

This query updates all documents with more than 50 comments to add the value “Frequently Discussed” in the genre array. MongoDB also allows us to replace a document with the replaceOne() operator.

3.8. Deleting Documents

Finally, let’s move on to our last CRUD operation, deletion. Like the other methods, deleting documents requires passing in a query filter, and deletes the first document it matches with.

Let’s delete the document we added earlier:

Bson deleteQuery = eq("title", "Silly Video");

collection.deleteOne(deleteQuery);
Copy

If, however, we wanted to delete multiple documents that match our query filter, we’d use the deleteMany(). Without any query filter, deleteMany() matches all documents in our collection. But if that is the goal, we should consider using the drop() method for better performance.

Let’s delete all the movies in the sample movie collection with a runtime of less than 60 minutes:

Bson query = lt("runtime", 60);

collection.deleteMany(query);Copy

This matches to and deletes all the documents in our collection with a runtime with a value less than 60.

4. Conclusion

This article was a quick introduction to using MongoDB from Java. We learned how to create documents and write them into our database, how to find these documents, update, and delete them. We also learned how to perform these operations on individual documents, or multiple documents at a time.

These are the basic database operations we need to get started with CRUD on our MongoDB database, but only touches the surface for what we can achieve with MongoDB and Java.

For more in-depth knowledge on using MongoDB with Java, the official MongoDB documentation provides quickstarts and usage guides, with plenty of sample code to get started. Alternatively, we can see the MongoDB Developer Center to learn more about how to use MongoDB with Java.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值