5. MongoDB and Java
Let's go to view hot to acces MongoDB from our Java programs. Firtsly, as we view in unit 2, we study how to acces directly and then with elements like ORM.
5.1. Drivers
As we already know, to connect from our applications to a database we need a controller or driver. MongoDB offers official drivers for a multitude of platforms, including C, C++, C#, NodeJS, Python, and of course, Java, among many others.
Focusing on Java, MongoDB offers us two drivers:
- The Java driver for synchronous applications.
- The Reactive Streams driver for processing asynchronous Streams.
Although currently there is a trend towards reactive programming, we are going to work with the Java synchronous driver to make it easier to understand and focus on the actual access to the data.
5.1.1. The Java driver
Using the MongoDB Driver for Java we can connect to both a local or remote database, as well as a MongoDB Atlas cluster. This driver (MongoDB Java Driver) can be found in the Maven repositories, and provides a large number of classes and interfaces to facilitate working with MongoDB from Java.
In a Gradle project we should use:
| Bash | |
|---|---|
whereas in a Maven project:
| XML | |
|---|---|
5.2. Connection to a database
To connect and communicate with a database we need a client. In the case of the Java driver for MongoDB, the client is implemented through the MongoClient class.
The MongoClient class represents a set of connections to a MongoDB server. These connections are thread-safe, that is, several threads of execution can safely access them.
The way to create MongoClient instances is through the MongoClients.create() method. Also, generally, we only need one instance of this class, even in multi-threaded applications. The MongoClients create method takes as an argument a Connection String, with the following simplified format (the clearer parameters are optional):
| Bash | |
|---|---|
So, a way to obtain, for example, a connection to the local server would be:
| Java | |
|---|---|
The MongoClient class, among others, supports the following methods:
getDatabase(String name)→ Gets a reference to a database whose name is passed as an argument.listDatabaseNames()Gets a list of Strings (MongoIterableinterface) with the names of the server's databases.close()Closes the connection to the server. It should always be done when it is no longer going to be used.
5.2.1. MongoDatabase
The getDatabase() method of the MongoClient class returns a reference to an object that implements the MongoDatabase interface, which represents a connection to a database. This interface defines the following methods:
getCollection(String name)→ Gets a reference to the collection.listCollectionNames()→ Gets a list of Strings (MongoIterable interface) with the names of the collections in the database.listCollections()→ Gets a list of references (MongoCollection) to the collections in the database.createCollection(String name)→ Creates a new collection with the specified name in the databasedrop()→ Drops the database
Here you will find a sample of connection and list of database and collections of a given server:
5.3. Queries
The getCollection() method of MongoDatabase() provides us with a Document collection (MongoCollection<Document>), on which we will be able to perform queries using the find() method. This method, which we already know from the MongoDB shell, will allow us to filter documents based on certain criteria.
These criteria are expressed as filters (query filters in the documentation), and can contain several query operators on some fields that will determine which documents in the collection are included as results.
The Filter class provides us with factory methods to perform these queries, similar to how we worked with the MongoDB shell. This class gives us:
- Empty query, with
Filters.empty(). - Comparison operators: To perform queries based on values in the collection:
Filters.eq(key, value),Filters.gt(key, value),Filters.gte(key, value),Filters.lt(key, value)orFilters.lte(key, value).- Logical operators: To perform logical operations on the result of other queries:
Filter.and(other_filters),Filter.or(other_folters), etc. - Array operators: They allow us to perform queries based on the value or number of elements of a vector:
Filters.size(vector, size). - Other operators, such as
Filter.exists()orFilter.regex(), to check for the existence of a key or perform a regular expression search.
In addition to filters, we will also be able to include aggregation operations, through the aggregate() method of a MongoCollection instance. You can check the documentation about aggregations in the MongoDB aggregation operations guide.
On the other hand, the MongoDB driver API also allows us to perform field projections using the Projections class, which offers the Projections.fields(), Projections.include() or Projections.excludeID() methods.
Sample of find films from a given year, only 10 resuts:
Remember
Document class have several method to work like Json Documents in unit 1. We can get each field by given key, getting its value
Another sample with filters and projections: