MongoDB Query to Find Ranking of Records in Spring Boot Java

  • Last updated Apr 25, 2024

Finding the rank of a document based on certain points or scores is straightforward and simple in Java Spring Boot.

Here is an example of how to find a user's rank by their ID based on their score:

{"_id" : ObjectId("60ed85c48325b33ee2b84f29"), "name": "A", "score": 700},
{"_id" : ObjectId("23ed85c48323b99es2b84f25"), "name": "B", "score": 500},
{"_id" : ObjectId("59ed85c48322b22ej2b84f22"), "name": "C", "score": 300},
{"_id" : ObjectId("89ed85c48328b31ed2b84f12"), "name": "D", "score": 600},
{"_id" : ObjectId("34ed85c48383b35eh2b84f84"), "name": "E", "score": 100},
{"_id" : ObjectId("89ed85c48323b73et2b84f54"), "name": "F", "score": 1000}

Here is an example of a method implementation to retrieve a user's rank by their ID:

public int getUserRank(String userId) {
    Optional<User> userOptional = userRepository.findById(userId);

    if (userOptional.isPresent()) {
      User user = userOptional.get();

      Criteria criteria = Criteria.where("score").gte(user.getScore());

      Aggregation agg = newAggregation(match(criteria), group("score").count().as("total"),
          project("total"), Aggregation.group().count().as("rank"));

      AggregationResults<UserRankCount> groupResults =
          mongoTemplate.aggregate(agg, User.class, UserRankCount.class);

      if (groupResults.getUniqueMappedResult() != null) {
        UserRankCount userRankCount = groupResults.getUniqueMappedResult();
        return user.getScore() > 0 ? userRankCount.getRank() : 0;
      }
    }
    return 0;
  }

The output of the above code for the user with the ID 89ed85c48328b31ed2b84f12 is as follows:

{"id" : "89ed85c48328b31ed2b84f12", "name": "D", "score": 600, "rank": 3}

To obtain the ranks of multiple users, you can retrieve all users from the database and iterate through them. While populating the rank of each user using the setRank() method, call the getUserRank() method by providing the user's userId, as shown in the example below:

  public Page<UserDTO> getUsersWithRanks(Pageable pageable) {
    Page<User> users = userRepository.findAll(pageable);

    List<UserDTO> userDTOs = new ArrayList<>();
    Page<UserDTO> pages = new PageImpl<>(userDTOs, pageable, 0);

    if (users.getSize() > 0) {
      users.getContent().forEach(user -> {
        UserDTO userDTO = new UserDTO();
        userDTO.setId(user.getId());
        userDTO.setName(user.getName());
        userDTO.setScore(user.getScore());

        // Calling getUserRank method to populate rank of each user
        userDTO.setRank(getUserRank(user.getId()));

        userDTOs.add(userDTO);
      });
      pages = new PageImpl<>(userDTOs, pageable, users.getTotalElements());
    }
    return pages;
  }

The output of the above code is as follows:

{"id" : "89ed85c48323b73et2b84f54", "name": "F", "score": 1000, "rank": 1},
{"id" : "60ed85c48325b33ee2b84f29", "name": "A", "score": 700, "rank": 2},
{"id" : "89ed85c48328b31ed2b84f12", "name": "D", "score": 600, "rank": 3},
{"id" : "59ed85c48322b22ej2b84f22", "name": "C", "score": 300, "rank": 4},
{"id" : "34ed85c48383b35eh2b84f84", "name": "E", "score": 100, "rank": 5}