loading...

MongoDB CRUD Queries from Java and Shell

pmgysel profile image Philipp Gysel ・6 min read

In this tutorial you will see working examples for performing CRUD operations to a MongoDB. We will consider 3 clients:

  • MongoDB Shell (supports JavaScript queries)
  • Java & Spring Boot: typed access via MongoRepository
  • Java: generic access via Documents / MongoCollection

les pyramides d'euseigne

Installation of MongoDB Server and Client

First make sure you have access to a MongoDB instance. There’s a variety of MongoDB distributions, including production-grade servers and cloud-hosted solutions. For this tutorial, I recommend you keep things simple and install MongoDB Community Server and MongoDB Compass locally.

You can get the installation for the MongoDB server here: https://www.mongodb.com/try/download/community. During the installation setup, you’ll be asked whether you want to install MongoDB Compass. Make sure to uncheck that box since you might end up with a (stable but older) version of Compass which doesn’t support a built-in MongoDB Shell. Apart from this, you can just go with the standard settings and click your way through the whole installation procedure.

Then, follow through with the compass installation, which you can find here: https://www.mongodb.com/products/compass. Make sure to pick version 1.22 or higher, this way you will get an integrated MongoDB Shell. After the installation, Compass will show the start screen. Just go with the default connection settings and hit “Connect”.

CRUD Ops With MongoDB Shell

At the bottom of your Compass GUI, you’ll see the MongoDB Shell. We’ll start by looking up all available databases and creating our own mydb database:

> show databases
> use mydb

Now we’re ready to create our first documents:

> db.company.insertOne({name:"Amazon", marketCap:1600})
> db.company.insertOne({name:"Google", marketCap:1010, foundingYear:1998})

In MongoDB, we can create collections by simply adding a document to a collection. So above, we created the collection company implicitly. Let’s have a look at the content of our collection:

> db.company.find()

This will return Amazon and Google as JSON strings. Two things to note here:

  • You can also view/edit/insert documents via Compass GUI
  • MongoDB is schemaless. If you have a close look at the Google Document, you’ll see the company has an extra field foundingYear.

MongoDB Compass GUI

Alright, let’s fire our first advanced read query:

> db.company.find({marketCap:{$gt:1500}})

Here our find query uses $gt (greater than) and only returns Amazon. More query filters are supported, like $eq, $lt, $in, etc.

Let’s consider one last read-query, which was pretty interesting for me, when I started using Document Databases:

> db.company.find({foundingYear:1998})

Here, we are searching for a company with founding year 1998. The fascinating point here is that not all companies contain this field, but MongoDB simply ignores companies without founding year.

Let's change an existing document:

> db.company.updateOne({name:"Google"},{$set:{name:"Alphabet"}})

The updateOne statement above searches for a company with the name “Google” and changes the name to “Alphabet”.

To wrap up this section, let’s delete a document:

> db.company.deleteOne({name:"Alphabet"})

Typed DB Access with Java + Spring Boot

So far, we’ve looked at how to experiment with MongoDB using the MongoDB Shell as client. In a real application though, you’d do all interactions with the DB programmatically. Let’s jump into a Java example. In this section, we leverage the MongoRepository interface from Spring Boot. This way of accessing the database can be considered “typed”, as all data reads / writes have the same structure.

With MongoRepository, the “schema” of our documents need to be defined in the application code, so let’s go ahead and create a POJO:

import org.springframework.data.annotation.Id;
public class Company {
  @Id
  public String _id;
  private String name;
  private Integer marketCap;
  // and constructor + setters + getters + toString method
}

Some uninteresting code lines are omitted for brevity. You can find all Java code with fully working examples on GitHub:

GitHub logo pmgysel / mongodb-java-crud-ops

MongoDB CRUD ops from Java. Two access ways: MongoRepository (type safe) or MongoCollection (generic).

MongoRepository has a powerful feature: One can define an extending class, and Spring Boot will automatically create a bean which implements the repository.

import org.springframework.data.mongodb.repository.MongoRepository;
public interface CompanyRepository
    extends MongoRepository<Company, String> {}

CompanyRepository will allow access to the company collection, and all documents from the DB will be represented as a Company. We’re ready to store our first companies:

@Autowired
CompanyRepository repository;
Company amazon = new Company("Amazon", 1600);
Company google = new Company("Google", 1010);
repository.save(amazon);
repository.save(google);
repository.findAll()
    .forEach(System.out::println);
// result:
// Company{_id='5f48ff8bf557ca416e52a6c4', name='Amazon', marketCap=1600}
// Company{_id='5f48ff8bf557ca416e52a6c5', name='Google', marketCap=1010}

The way we interacted with the repository was via its MongoRepository interface methods which include: save, findAll, findById, delete, etc.

Moreover, we can define additional query methods in our CompanyRepository. Let’s add a method to find a company by name and another method that searches by minimum marketCap:

public interface CompanyRepository
    extends MongoRepository<Company, String> {
  List<Company> findByName(String name);
  List<Company> findByMarketCapGreaterThan(Integer marketCap);
}

// and then use the custom queries:
repository.findByName("Amazon");
repository.findByMarketCapGreaterThan(1500);

In order to update an existing document, you can first search for that company, use its setter methods to modify it, and then save it again:

Company aCompany = repository.findByName("Google").get(0);
aCompany.setName("Alphabet");
repository.save(aCompany);

Finally, you can delete a company as follows:

repository.deleteById(aCompany.get_id());

Untyped DB Access with Java

Here we show a 3rd way for accessing the DB, in a totally generic and schemaless fashion. All access now happens through Documents which can hold arbitrary data. MongoCollection offers low-level access to the DB and we can dynamically look at fields inside a document and act accordingly.

Let’s start by initializing our MongoCollection:

MongoClient client = MongoClients.create();
MongoDatabase db = client.getDatabase("mydb");
MongoCollection<Document> collection = db.getCollection("company");

Persist a document:

Document google = new Document()
    .append("name", "Google")
    .append("marketCap", 1010);
collection.insertOne(google);

Note that the interface of MongoCollection only accepts Documents, which is basically a nested map of key-value pairs. Thanks to the dynamic content of a given Document, we can store any fields we want to.

For read queries, we can use eq (is equal):

List<Document> google = new ArrayList<>();
collection.find(eq("name", "Google")).into(google);
google.forEach(System.out::println);

Many more query Filters are supported like gt, lt, and, or, exists, ne, etc. As a case in point, let’s search for companies which contain a field marketCap but don’t have the name “Google”:

collection.find(and(exists("marketCap"), ne("name", "Google")))

Compared to the previous section, the query results aren't typed, we therefore need capability to inspect Documents:

Optional<String> inspectDocument(Document document, String key) {
  return Optional.ofNullable(document.get(key))
      .map(Object::toString);
}

The above code snippet shows how to check whether a key exists and if so, serializes it into a String.

To wrap this tutorial up, here's how to update and delete a document:

collection.updateOne(eq("name", "Google"), set("name", "Alphabet"));
collection.deleteOne(eq("name", "Alphabet"));

Conclusion

We made it😀🥂 Now you know how to perform CRUD operations on a MongoDB from Java!

To sum up, MongoDB offers a powerful query language to manipulate documents of varying schema. for experimental purposes, you can use the MongoDB Shell. In this post, we focused on the Java client. Note though that MongoDB offers clients in pretty much every language, including JavaScript (Node.js), Python, and Go.

You can find all Java code with fully working examples on GitHub:

GitHub logo pmgysel / mongodb-java-crud-ops

MongoDB CRUD ops from Java. Two access ways: MongoRepository (type safe) or MongoCollection (generic).

Let me know about your feedback / questions and leave a like❤️

Discussion

pic
Editor guide
Collapse
chuchhin profile image
Jesús Sánchez

Hi, interesting.

have you used Morphia ? It's a good tool. I used for many projects but the performance it's not the better (i talk for me).

Collapse
pmgysel profile image
Philipp Gysel Author

Hey Jesús, thanks! I personally haven't used Morphia yet but it looks like a cool tool! It's always good to know tools that'll make your life easier:) I know for JavaScript, lots of people use Mongoose... Anyways, in this tutorial I concentrated on using as few external libraries as possible - actually only SpringBoot - which lots of backend Java projects already use anyways...