NoSQL Top

Build a Dashboard Using Cassandra, Astra, and Stargate:

>> CHECK OUT THE ARTICLE
Persistence top

Get started with Spring Data JPA through the reference Learn Spring Data JPA course:

>> CHECK OUT THE COURSE

1. Overview

When using Spring Data MongoDB, we may need to log to a higher level than the default one. Typically, we may need to see, for example, some additional information such as statement executions or query parameters.

In this short tutorial, we'll see how to modify the MongoDB logging level for queries.

2. Configure MongoDB Queries Logging

MongoDB Support offers the MongoOperations interface or its primary MongoTemplate implementation to access data, so all we need is to configure a debug level for the MongoTemplate class.

Like any Spring or Java application, we can use a logger library and define a logging level for MongoTemplate.

Typically, we can write in our configuration file something like:

<logger name="org.springframework.data.mongodb.core.MongoTemplate" level="DEBUG" />

However, if we're running a Spring Boot application, we can configure this in our application.properties file:

logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG

Likewise, we can use the YAML syntax:

logging:
  level:
    org:
      springframework:
        data:
          mongodb:
            core:
              MongoTemplate: DEBUG

3. Test Class for Logging

First, let's create a Book class:

@Document(collection = "book")
public class Book {

    @MongoId
    private ObjectId id;
    private String bookName;
    private String authorName;

    // getters and setters
}

We want to create a simple test class and check out logs.

To demonstrate this, we use Embedded MongoDB. To be sure, let's check our dependencies first:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <version>${embed.mongo.version}</version>
    <scope>test</scope>
</dependency>

Finally, let's define our test class using Spring Boot Test:

@SpringBootTest
@TestPropertySource(properties = { "logging.level.org.springframework.data.mongodb.core.MongoTemplate=DEBUG" })
public class LoggingUnitTest {

    private static final String CONNECTION_STRING = "mongodb://%s:%d";

    private MongodExecutable mongodExecutable;
    private MongoTemplate mongoTemplate;

    @AfterEach
    void clean() {
        mongodExecutable.stop();
    }

    @BeforeEach
    void setup() throws Exception {
        String ip = "localhost";
        int port = 27017;

        ImmutableMongodConfig mongodbConfig = MongodConfig.builder()
          .version(Version.Main.PRODUCTION)
          .net(new Net(ip, port, Network.localhostIsIPv6()))
          .build();

        MongodStarter starter = MongodStarter.getDefaultInstance();
        mongodExecutable = starter.prepare(mongodbConfig);
        mongodExecutable.start();
        mongoTemplate = new MongoTemplate(MongoClients.create(String.format(CONNECTION_STRING, ip, port)), "test");
    }
    // tests
}

4. Log Samples

In this section, we'll define some simple test cases and show the relative logs to test the most common scenarios, such as finding, inserting, updating, or aggregating of Documents.

4.1. Insert

First, let's start with inserting a single Document:

Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");

mongoTemplate.insert(book);

The logs show in which collection we are inserting. When finding a Document, the id is also logged:

[2022-03-20 17:42:47,093]-[main] DEBUG MongoTemplate - Inserting Document containing fields: [bookName, authorName, _class] in collection: book
...
[2022-03-20 17:42:47,144]-[main] DEBUG MongoTemplate - findOne using query: { "id" : { "$oid" : "623759871ff6275fe96a5ecb"}} fields: Document{{}} for class: class com.baeldung.mongodb.models.Book in collection: book
[2022-03-20 17:42:47,149]-[main] DEBUG MongoTemplate - findOne using query: { "_id" : { "$oid" : "623759871ff6275fe96a5ecb"}} fields: {} in db.collection: test.book

4.2. Update

Likewise, when updating a Document:

Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");

mongoTemplate.insert(book);

String authorNameUpdate = "AuthorNameUpdate";

book.setAuthorName(authorNameUpdate);
mongoTemplate.updateFirst(query(where("bookName").is("Book")), update("authorName", authorNameUpdate), Book.class);

We can see the actual updated Document field in the logs:

[2022-03-20 17:48:31,759]-[main] DEBUG MongoTemplate - Calling update using query: { "bookName" : "Book"} and update: { "$set" : { "authorName" : "AuthorNameUpdate"}} in collection: book

4.3. Batch Insert

Let's add an example for a batch insertion:

Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");

Book book1 = new Book();
book1.setBookName("Book1");
book1.setAuthorName("Author1");

mongoTemplate.insert(Arrays.asList(book, book1), Book.class);

We can see the number of inserted Documents in the logs:

[2022-03-20 17:52:00,564]-[main] DEBUG MongoTemplate - Inserting list of Documents containing 2 items

4.4. Remove

Also, let's add an example for removing:

Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");

mongoTemplate.insert(book);

mongoTemplate.remove(book);

We can see in the logs, in this case, the id of the deleted Document:

[2022-03-20 17:56:42,151]-[main] DEBUG MongoTemplate - Remove using query: { "_id" : { "$oid" : "62375cca2a2cba4db774d8c1"}} in collection: book.

4.5. Aggregation

Let's see an example for Aggregation. In this case, we need to define a result class. For example, we'll aggregate by the author name:

public class GroupByAuthor {

    @Id
    private String authorName;
    private int authCount;

    // getters and setters
}

Next, let's define a test case for grouping:

Book book = new Book();
book.setBookName("Book");
book.setAuthorName("Author");

Book book1 = new Book();
book1.setBookName("Book1");
book1.setAuthorName("Author");

Book book2 = new Book();
book2.setBookName("Book2");
book2.setAuthorName("Author");

mongoTemplate.insert(Arrays.asList(book, book1, book2), Book.class);

GroupOperation groupByAuthor = group("authorName")
  .count()
  .as("authCount");

Aggregation aggregation = newAggregation(groupByAuthor);

AggregationResults<GroupByAuthor> aggregationResults = mongoTemplate.aggregate(aggregation, "book", GroupByAuthor.class);

We can see in the logs by which field we have aggregated and what kind of aggregation pipeline:

[2022-03-20 17:58:51,237]-[main] DEBUG MongoTemplate - Executing aggregation: [{ "$group" : { "_id" : "$authorName", "authCount" : { "$sum" : 1}}}] in collection book

5. Conclusion

In this article, we looked at how to enable a debug logging level for Spring Data MongoDB.

We've defined some common query scenarios and looked at their relative logs while doing some live tests.

As always, the code for these examples is available over on GitHub.

NoSql Bottom

Build a Dashboard Using Cassandra, Astra, and Stargate

>> CHECK OUT THE ARTICLE
Persistence bottom
Get started with Spring Data JPA through the reference Learn Spring Data JPA course: >> CHECK OUT THE COURSE
Persistence footer banner
Comments are closed on this article!