Допустим, у меня есть классы, иллюстрирующие проблему песен и голосов, за которые проголосовали.
Пользователь. java
@EqualsAndHashCode
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Document(collection = "users")
public class User {
@Id private String id;
private String username;
private String email;
private Integer age;
private String password;
@DBRef(db = "interview", lazy = true)
@EqualsAndHashCode.Exclude
@ToString.Exclude
private Set<Song> songs;
}
Песня. java
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Song {
@Id private String id;
private String title;
private String author;
private SongGenre songGenre;
Set<Vote> votesOfSong;
}
Голосовать. java
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "votes")
@Getter
public class Vote {
@Id private String id;
private User user;
private Song song;
private VoteKind voteKind;
@Default private LocalDateTime dateOfVote = LocalDateTime.now();
}
и
VoteKind. java
@RequiredArgsConstructor
@Getter
public enum VoteKind {
LIKE(1),
DISLIKE(-1);
private final Integer voteValue;
}
Я хочу создать метод, который будет возвращать наиболее распространенные SongGenre
, SongTitle
и количество голосов для конкретной песни.
Пока у меня есть такие методы, как:
public Flux<Map<Song, SongGenre>> theMostCommonSongForSongGenre(SongGenre songGenre) {
voteRepository
.findAll()
.collect(
Collectors.toMap(vote -> vote.getSong().getSongGenre(), this::getSumOfVotesForVote))
.map(Map::entrySet)
.flatMapMany(Flux::fromIterable)
.filter(stringListEntry -> stringListEntry.getKey().equals(songGenre))
.sort(Map.Entry.comparingByKey(Comparator.reverseOrder()))
.collect(Collectors.toMap(o -> o.getKey(), o -> o.getValue()));
}
и вспомогательный метод:
private int getSumOfVotesForSong(Vote vote) {
return vote.getSong().getVotesOfSong().stream()
.mapToInt(voteKind -> vote.getVoteKind().getVoteValue())
.sum();
}
Здесь есть две проблемы, которые я не могу полностью решить.
Как ограничить результат моего Flux, например, 1 или 10 записями. Традиционно, в Java Stream API я могу использовать методы findFirst
или limit
, но здесь нет другого эквивалентного метода. Единственный метод, который я могу вызвать - это limitRate
, но у него есть другое предназначение.
Как преобразовать текущее решение, чтобы получить SongGenre
, SongTitle
и количество голосов для конкретной песни , Есть ли шанс вернуть MultiMap для вышеуказанных параметров, или я должен использовать groupingBy
и вернуть пользовательский объект с songGenre
и songTitle
в качестве ключа и в качестве значения Integer, которое будет эквивалентно количеству голосов.
EDIT: Core java потоковое решение может быть любым.
Буду благодарен за предложения о том, как достичь цели.