Skip to main content

Command Palette

Search for a command to run...

Designing and Developing a Search API with Spring Boot

Updated
5 min read
Designing and Developing a Search API with Spring Boot
V

Solutions Architect | Product Design & Development | Cloud-Native Microservices | Distributed Applications (Back-End)

You've probably seen search features on most websites and apps these days. Most of these websites use a backend search API to fetch the results and display them to users. In this article, we're going to dive into how to design and develop a search API using Spring Boot.

We will take tutorials search as an example for the search API. At a high level, the tutorial search api takes a tutorial title as a search query and returns the relevant results in the response. Let’s discuss on the requirements and the desired functionality of the search api before we discuss on the API design.

Understanding the Core Requirements

Searching: The API should return data for the requested search query.

Sorting: The API should sort the data according to the client’s request. Sorting can be either ascending or descending order. By default, we will have Ascending sorting.

Pagination: The API should support pagination functionality as it is difficult to manage the data when there is a huge data.

Filter: Filtering can help narrow down the search results further.

Design Consideration

Architectural Style: We will utilize REST architectural style as the search api is mainly resource-oriented and best suited for client and server communication.

Data format: When talking about data format, we will use JSON as it is easy to render in the client’s browser and also best suited for REST architectural style.

API Model & Contract

We will model the API to meet the functional requirements while following the best practices.

URL:

 https://techstackengineer.com/api/v1/tutorials/search?query=java&page=0&size=10&sort=title&sortOrder=DSC

Base URL domain: “techstackengineer.com” shown here as a base url domain is for illustration purpose only. if you are running the code in your local, you can use localhost:{port} as a base domain.

Search Key: The “query” request parameter is used for passing the search key word.

Pagination: Fetching all the tutorials in a single API request when there are thousands of records may not effective. This can burden the server and results in a poor good user experience by displaying thousands of tutorials at once on the screen.

For this purpose, we can use “page” and “size” request parameters. page starts with 0 and we can choose size of each page as needed.

Sorting: Sorting is an additional feature that can be applied on any field in the search api. We can pass the sort field in “sort” request parameter and also choose to provide the “sortOrder.”

Building the Search API with Spring Boot:

Our project structure will look similar to a typical spring boot project. You can use spring initializer https://start.spring.io/ to start creating a spring boot project.

Implementing the Controller:

First, let’s create TutorialController class using Spring annotations. The request parameters can be optional and be passed as needed to the search api.

@RestController
@RequestMapping("/api/v1/tutorials")
public class TutorialController {

    @Autowired
    TutorialService tutorialService;

    @GetMapping("/search")
    public ResponseEntity<SearchResponse> search(@RequestParam(required = false) String query,
                                                @RequestParam(defaultValue = "0") int page,
                                                @RequestParam(defaultValue = "10") int size,
                                                @RequestParam(required = false) String sort,
                                                @RequestParam(required = false) String sortOrder,
                                                @RequestParam(required = false) String filter,
                                                @RequestParam(required = false) String category) {

        RequestCriteria requestCriteria = new RequestCriteria(query, page, size, sort, sortOrder, filter, category);
        Page<Tutorial> tutorialPage = tutorialService.findTutorialsByPagingAndSorting(requestCriteria);
        SearchResponse searchResponse = new SearchResponse(tutorialPage.getContent(), tutorialPage.getTotalPages(),
                tutorialPage.getTotalElements(), tutorialPage.getNumber());
        return new ResponseEntity<>(searchResponse, HttpStatus.OK);
    }

Configuring the Database: We will use the H2 in-memory database for our search api and below is the application.yml configuration.

spring:
  application:
    name: search-api
  datasource:
    url: jdbc:h2:mem:mydb
    username: sa
    password:
    driverClassName: org.h2.Driver
  h2:
    console:
      enabled: true
      path: /console/
  jpa:
    database-platform: org.hibernate.dialect.H2Dialect
    defer-datasource-initialization: true
    #hibernate:
     # ddl-auto: none
logging:
  level:
    root: INFO

Here, I am setting “defer-datasource-initialization” property to true. This will ensure that after hibernate schema creation is done, then additionally data.sql file will be executed. We are using “data.sql” file to load tutorials data during the application startup.

Defining the Tutorial Entity:

First, We will have a tutorial entity as our domain class.

@Entity
@Table(name = "tutorials")
public class Tutorial {
    @Id
    private Long id;
    private String title;
    private String description;
    private String category;
    private String publishedDate;

    public Tutorial() {
    }
}

Creating the Repository:

We will need a repository to access our tutorial entity. We can create tutorial repository by extending JpaRepository class.

Here, We are passing “Pageable” object to all the repository methods to achieve the pagination and sorting functionalities. These methods are used in different scenarios based on the input requests and results will contain a page object.

public interface TutorialRepository extends JpaRepository<Tutorial, Long> {

    Page<Tutorial> findByTitleContainingIgnoreCase(String title, Pageable pageable);

    Page<Tutorial> findByTitleContainingIgnoreCaseAndCategoryIgnoreCase(String title, String category,
                                                                        Pageable pageable);
    Page<Tutorial> findByCategoryIgnoreCase(String category, Pageable pageable);
}

Enhancing with Pagination and Sorting:

We can create PageRequest object by passing current page number and size (number of records)of the page. page number starts at 0.

PageRequest pageRequest = PageRequest.of(0, 10);

We can also do sorting along with pagination. This can be achieved by passing the sort object to the PageRequest as shown below.

The sort can be applied for any field like “title” or “description” as needed.

PageRequest pageRequest = PageRequest.of(0, 10, Sort.by(Sort.Direction.DESC, "title"));

API Request & Response Structure:

Request:

http://localhost:8080/api/v1/tutorials/search?query=java&page=0&size=10&sort=title&sortOrder=ASC

Response:

{
  "tutorials": [
    {
      "id": 96,
      "title": "Java API Design",
      "description": "Best practices for designing APIs in Java.",
      "category": "Java",
      "publishedDate": "2024-09-13"
    },
    {
      "id": 1,
      "title": "Java Basics",
      "description": "Introduction to Java programming language.",
      "category": "Java",
      "publishedDate": "2024-01-15"
    },
    {
      "id": 51,
      "title": "Java Collections Framework",
      "description": "Deep dive into Java Collections Framework.",
      "category": "Java",
      "publishedDate": "2024-09-13"
    },
    {
      "id": 66,
      "title": "Java Concurrency",
      "description": "Understanding concurrency and multithreading in Java.",
      "category": "Java",
      "publishedDate": "2024-09-13"
    },
    {
      "id": 82,
      "title": "Java Functional Programming",
      "description": "Introduction to functional programming in Java.",
      "category": "Java",
      "publishedDate": "2024-09-13"
    }
  ],
  "totalPages": 3,
  "totalItems": 13,
  "currentPage": 0
}

Github Project:

The spring boot project for this search api is available at below repo. Please check “search-api” module inside this repo.

https://github.com/techstackengineer/spring-boot-tutorials

Conclusion:

Designing and developing a search API using Spring Boot involves understanding the key requirements such as searching, sorting, pagination, and filtering. By adopting a REST architectural style and utilizing JSON data format, we ensure efficient client-server communication.

The API model and contract are structured to meet functional needs while adhering to best practices.

Implementing features like pagination and sorting through Spring Boot's repository and PageRequest functionalities enhances the API's performance and user experience.

By following these guidelines, we can create robust and scalable search APIs that effectively handle large datasets and provide relevant search results to users.