api: optimize pagination!!
Some checks failed
Deploy API / docker (17, 3.8.5) (push) Failing after 30s
Some checks failed
Deploy API / docker (17, 3.8.5) (push) Failing after 30s
This commit is contained in:
parent
1f1c55d41f
commit
131a5c2efe
@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -17,10 +18,15 @@ public class PaginationBuilder<T> {
|
|||||||
*/
|
*/
|
||||||
private int itemsPerPage;
|
private int itemsPerPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of items.
|
||||||
|
*/
|
||||||
|
private int totalItems;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The items to paginate.
|
* The items to paginate.
|
||||||
*/
|
*/
|
||||||
private List<T> items;
|
private Function<FetchItems, List<T>> items;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the number of items per page.
|
* Sets the number of items per page.
|
||||||
@ -33,14 +39,25 @@ public class PaginationBuilder<T> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the total number of items.
|
||||||
|
*
|
||||||
|
* @param totalItems The total number of items.
|
||||||
|
* @return The pagination builder.
|
||||||
|
*/
|
||||||
|
public PaginationBuilder<T> totalItems(Supplier<Integer> totalItems) {
|
||||||
|
this.totalItems = totalItems.get();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the items to paginate.
|
* Sets the items to paginate.
|
||||||
*
|
*
|
||||||
* @param getItems The items to paginate.
|
* @param getItems The items to paginate.
|
||||||
* @return The pagination builder.
|
* @return The pagination builder.
|
||||||
*/
|
*/
|
||||||
public PaginationBuilder<T> fillItems(Supplier<List<T>> getItems) {
|
public PaginationBuilder<T> items(Function<FetchItems, List<T>> getItems) {
|
||||||
this.items = getItems.get();
|
this.items = getItems;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,19 +77,39 @@ public class PaginationBuilder<T> {
|
|||||||
* @return The page.
|
* @return The page.
|
||||||
*/
|
*/
|
||||||
public Page<T> getPage(int page) {
|
public Page<T> getPage(int page) {
|
||||||
int totalItems = this.items.size();
|
List<T> items = this.items.apply(new FetchItems(page, this.itemsPerPage));
|
||||||
int totalPages = (int) Math.ceil((double) totalItems / this.itemsPerPage);
|
int totalPages = (int) Math.ceil((double) this.totalItems / this.itemsPerPage);
|
||||||
|
|
||||||
if (page < 1 || page > totalPages) {
|
if (page < 1 || page > totalPages) {
|
||||||
throw new BadRequestException("Invalid page number");
|
throw new BadRequestException("Invalid page number");
|
||||||
}
|
}
|
||||||
List<T> items = this.items.subList((page - 1) * this.itemsPerPage, Math.min(page * this.itemsPerPage, totalItems));
|
|
||||||
return new Page<>(
|
return new Page<>(
|
||||||
items,
|
items,
|
||||||
new Page.Metadata(page, totalPages, totalItems)
|
new Page.Metadata(page, totalPages, this.totalItems)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public static class FetchItems {
|
||||||
|
/**
|
||||||
|
* The current page.
|
||||||
|
*/
|
||||||
|
private final int currentPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The items per page.
|
||||||
|
*/
|
||||||
|
private final int itemsPerPage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of items to skip.
|
||||||
|
*/
|
||||||
|
public int skipAmount() {
|
||||||
|
return (currentPage - 1) * itemsPerPage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@Getter
|
@Getter
|
||||||
public static class Page<T> {
|
public static class Page<T> {
|
||||||
|
@ -31,4 +31,18 @@ public class ScoreSaberScoreResponse extends ScoreSaberScore {
|
|||||||
this.user = user;
|
this.user = user;
|
||||||
this.leaderboard = leaderboard;
|
this.leaderboard = leaderboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new score saber score response.
|
||||||
|
*
|
||||||
|
* @param score the score to create the response from
|
||||||
|
* @param user the user that set the score
|
||||||
|
* @param leaderboard the leaderboard the score was set on
|
||||||
|
* @return the score saber score response
|
||||||
|
*/
|
||||||
|
public static ScoreSaberScoreResponse fromScore(ScoreSaberScore score, UserDTO user, Leaderboard leaderboard) {
|
||||||
|
return new ScoreSaberScoreResponse(score.getId(), score.getPlayerId(), score.getPlatform(), score.getPlatformScoreId(), score.getLeaderboardId(),
|
||||||
|
score.getRank(), score.getAccuracy(), score.getPp(), score.getScore(), score.getModifiers(), score.getMisses(), score.getBadCuts(),
|
||||||
|
score.getDeviceInformation(), score.getTimestamp(), score.getWeight(), score.getMultiplier(), score.getMaxCombo(), user, leaderboard);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,9 +24,10 @@ public interface ScoreRepository extends MongoRepository<Score, Long> {
|
|||||||
@Aggregation(pipeline = {
|
@Aggregation(pipeline = {
|
||||||
"{ $match: { platform: ?0, pp: { $gt: 0 } } }",
|
"{ $match: { platform: ?0, pp: { $gt: 0 } } }",
|
||||||
"{ $sort: { pp: -1 } }",
|
"{ $sort: { pp: -1 } }",
|
||||||
|
"{ $skip: ?2 }",
|
||||||
"{ $limit: ?1 }",
|
"{ $limit: ?1 }",
|
||||||
})
|
})
|
||||||
List<Score> getTopRankedScores(@NonNull Platform.Platforms platform, int amount);
|
List<Score> getTopRankedScores(@NonNull Platform.Platforms platform, int amount, int skip);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets all the ranked scores from the platform.
|
* Gets all the ranked scores from the platform.
|
||||||
|
@ -80,36 +80,17 @@ public class ScoreService {
|
|||||||
*/
|
*/
|
||||||
public PaginationBuilder.Page<ScoreSaberScoreResponse> getTopRankedScores(@NonNull Platform.Platforms platform, int pageNumber, boolean scoresOnly) {
|
public PaginationBuilder.Page<ScoreSaberScoreResponse> getTopRankedScores(@NonNull Platform.Platforms platform, int pageNumber, boolean scoresOnly) {
|
||||||
PaginationBuilder<ScoreSaberScoreResponse> builder = new PaginationBuilder<ScoreSaberScoreResponse>().build();
|
PaginationBuilder<ScoreSaberScoreResponse> builder = new PaginationBuilder<ScoreSaberScoreResponse>().build();
|
||||||
builder.itemsPerPage(50);
|
builder.itemsPerPage(15);
|
||||||
builder.fillItems(() -> {
|
builder.totalItems(() -> this.scoreRepository.getTotalRankedScores(platform));
|
||||||
List<Score> foundScores = this.scoreRepository.getTopRankedScores(platform, 250);
|
builder.items((fetchItems) -> {
|
||||||
|
List<Score> foundScores = this.scoreRepository.getTopRankedScores(platform, fetchItems.getItemsPerPage(), fetchItems.skipAmount());
|
||||||
List<ScoreSaberScoreResponse> scores = new ArrayList<>();
|
List<ScoreSaberScoreResponse> scores = new ArrayList<>();
|
||||||
for (Score score : foundScores) {
|
for (Score score : foundScores) {
|
||||||
ScoreSaberScore scoreSaberScore = (ScoreSaberScore) score;
|
ScoreSaberScore scoreSaberScore = (ScoreSaberScore) score;
|
||||||
UserDTO user = scoresOnly ? null : userService.getUser(score.getPlayerId()).getAsDTO();
|
UserDTO user = scoresOnly ? null : userService.getUser(score.getPlayerId()).getAsDTO();
|
||||||
Leaderboard leaderboard = scoresOnly ? null : Leaderboard.getFromScoreSaberToken(scoreSaberService.getLeaderboard(score.getLeaderboardId()));
|
Leaderboard leaderboard = scoresOnly ? null : Leaderboard.getFromScoreSaberToken(scoreSaberService.getLeaderboard(score.getLeaderboardId()));
|
||||||
|
|
||||||
scores.add(new ScoreSaberScoreResponse(
|
scores.add(ScoreSaberScoreResponse.fromScore(scoreSaberScore, user, leaderboard));
|
||||||
score.getId(),
|
|
||||||
score.getPlayerId(),
|
|
||||||
score.getPlatform(),
|
|
||||||
score.getPlatformScoreId(),
|
|
||||||
score.getLeaderboardId(),
|
|
||||||
score.getRank(),
|
|
||||||
score.getAccuracy(),
|
|
||||||
score.getPp(),
|
|
||||||
score.getScore(),
|
|
||||||
score.getModifiers(),
|
|
||||||
score.getMisses(),
|
|
||||||
score.getBadCuts(),
|
|
||||||
score.getDeviceInformation(),
|
|
||||||
score.getTimestamp(),
|
|
||||||
scoreSaberScore.getWeight(),
|
|
||||||
scoreSaberScore.getMultiplier(),
|
|
||||||
scoreSaberScore.getMaxCombo(),
|
|
||||||
user,
|
|
||||||
leaderboard
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
return scores;
|
return scores;
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user