Howard Paget
Projects
About

Spring Boot: Using MongoDB

Jun 11, 2023
java

In this article, we’ll use Spring Data MongoDB to save data and query data from MongoDB. We’ll create a very simple content management system (CMS) which allows users to create and retrieve posts.

This article assumes some familiarity with Spring Data and MongoDB/document databases.

You can check out a complete example on GitHub: https://github.com/howardpaget/mongo-cms-example.

Required Dependencies

We’ll need the spring-boot-starter-data-mongodb library which provides methods for performing CRUD (Create, Read, Update, Delete) operations via the MongoRepository class.

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'

MongoDB Connection Configuration

Connection configuration is provided in the application.yaml (or application.properties) like so:

spring:
  data:
    mongodb:
      host: localhost
      port: 27017
      authentication-database: admin
      database: cms
      username: app
      password: password

The Post Document

To store data in MongoDB we need a class that represents the document to be stored.

The @Id marks the field id as the id of the document. The @Document("posts") indicates that the class is a document that is stored in the “posts” collection.

@Document("posts")
public class Post {

  @Id
  private final String id;

  private String title;
  private String authorId;
  private String author;
  private LocalDateTime publishedDateTime;
  private List<String> tags;
  private String body;

  public Post(String id, String title, String authorId, String author,
      LocalDateTime publishedDateTime, List<String> tags, String body) {
    this.id = id;
    this.title = title;
    this.authorId = authorId;
    this.author = author;
    this.publishedDateTime = publishedDateTime;
    this.tags = tags;
    this.body = body;
  }

  // getters and setters ...
}

Spring Data MongoDB Repository

Below we define PostRepository which is our class for persisting, querying, etc posts stored in MongoDB. Out of the box extending the MongoRepository provides the save, findAll, etc methods.

Additional functionality can be achieved using the Spring Data repository query derivation mechanism. For example, the findAllByPublishedDateTimeBetween method is translated into the query:

{ $and: [ { publishedDateTime: { $gt: ?0 } }, { publishedDateTime: { $lt: ?1 } } ] }

More complex additional functionality can be added using one of @Query, @CountQuery, @DeleteQuery, @ExistsQuery, or @Aggregation and providing the query as a string.

public interface PostRepository extends MongoRepository<Post, String> {

  List<Post> findAllByPublishedDateTimeBetween(LocalDateTime from, LocalDateTime to);

  @Query("{ 'tags': { $all: ?0 } }")
  List<Post> findAllTaggedWith(List<String> tags);

  @Aggregation(pipeline = """
      {
        $group: {
          _id: { $dateToString: { date: '$publishedDateTime', format: '%Y-%m-01' } },
          count: { $sum: 1 }
        }
      }
      """)
  List<Count> countByMonth();
}

Using the MongoDB Repository

With the PostRepository defined, we can inject it into our components that need it. For example, in the controller below the repository is used directly to save the post provided in the request and get all posts.

@RestController
public class PostController {

  private final PostRepository postRepository;

  public PostController(PostRepository postRepository) {
    this.postRepository = postRepository;
  }

  @PostMapping("/posts")
  public Post createPost(@RequestBody PostRequest post) {
    return postRepository.save(new Post(null, post.title(), post.authorId(), author.getName(),
        post.publishedDateTime(), post.tags(), post.body()));
  }

  @GetMapping("/posts")
  public List<Post> getPosts() { 
    return postRepository.findAll();
  }
}

Running MongoDB using Docker Compose

To run locally you’ll need an instance of MongoDB running. The Docker Compose YAML below will start an instance of MongoDB and MongoDB Express a simple web-based tool for inspecting MongoDB.

version: '3.1'

services:

  mongo:
    image: mongo
    restart: always
    ports:
      - 27017:27017
    environment:
      MONGO_INITDB_ROOT_USERNAME: app
      MONGO_INITDB_ROOT_PASSWORD: password

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    environment:
      ME_CONFIG_MONGODB_ADMINUSERNAME: app
      ME_CONFIG_MONGODB_ADMINPASSWORD: password
      ME_CONFIG_MONGODB_URL: mongodb://app:password@mongo:27017/

Complete Example

You can check out a complete example on GitHub: https://github.com/howardpaget/mongo-cms-example.