MongoDB Query to Find Ranking of Records in Spring Boot Java

To find the rank of a document on basis of some points or score is very simple and straightforward in Java Spring Boot.

Here is an example, to find the rank of a user by id, on basis of his score:

Following is a sample of Users Data:

{"_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}

Method implementation to get rank of a user by 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 above code will give the following output for user id 89ed85c48328b31ed2b84f12:

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

To get ranks of multiple users, you can simply use the above method 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());
                userDTO.setRank(getUserRank(user.getId()));

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

The above code will give the following output:

{"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}