Skip to content

Commit

Permalink
feat: 노출 처리가 된 무작위 5개의 토픽을 조회하는 API 구현 (#333)
Browse files Browse the repository at this point in the history
  • Loading branch information
kdkdhoho committed Dec 12, 2024
1 parent 9b9767e commit f66e606
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
Expand All @@ -25,7 +26,7 @@
@AllArgsConstructor
public class Topic extends BaseEntity {

@ManyToOne
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false, foreignKey = @ForeignKey(name = "topic_user_fk"))
private User user;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.listywave.list.application.domain.category.CategoryType;
import com.listywave.topic.application.domain.Topic;
import com.listywave.topic.application.service.dto.ExposedTopicFindResponse;
import com.listywave.topic.application.service.dto.RecommendTopicFindResponse;
import com.listywave.topic.application.service.dto.TopicCreateRequest;
import com.listywave.topic.application.service.dto.TopicFindResponse;
import com.listywave.topic.repository.TopicRepository;
Expand Down Expand Up @@ -45,4 +46,9 @@ public void update(Long topicId, boolean isExposed, String categoryCode, String
Topic topic = topicRepository.getById(topicId);
topic.update(isExposed, CategoryType.codeOf(categoryCode), title);
}

public List<RecommendTopicFindResponse> findRecommendTopics() {
List<Topic> topics = topicRepository.get5TopicsRandomly();
return RecommendTopicFindResponse.toList(topics);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.listywave.topic.application.service.dto;

import com.listywave.topic.application.domain.Topic;
import java.util.List;

public record RecommendTopicFindResponse(
Long id,
String title
) {

public static List<RecommendTopicFindResponse> toList(List<Topic> topics) {
return topics.stream()
.map(topic -> new RecommendTopicFindResponse(topic.getId(), topic.getTitle().getValue()))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import com.listywave.common.auth.Auth;
import com.listywave.topic.application.service.TopicService;
import com.listywave.topic.application.service.dto.ExposedTopicFindResponse;
import com.listywave.topic.application.service.dto.RecommendTopicFindResponse;
import com.listywave.topic.application.service.dto.TopicCreateRequest;
import com.listywave.topic.application.service.dto.TopicFindResponse;
import com.listywave.topic.presentation.dto.TopicUpdateRequest;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -37,6 +39,12 @@ ResponseEntity<ExposedTopicFindResponse> findAllExposed(
return ResponseEntity.ok(result);
}

@GetMapping("/topics/recommend")
ResponseEntity<List<RecommendTopicFindResponse>> recommendTopics() {
List<RecommendTopicFindResponse> result = topicService.findRecommendTopics();
return ResponseEntity.ok(result);
}

@GetMapping("/admin/topics")
ResponseEntity<TopicFindResponse> findAll(
@RequestParam(required = false) Long cursorId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@

import com.listywave.common.exception.CustomException;
import com.listywave.topic.application.domain.Topic;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;

public interface TopicRepository extends JpaRepository<Topic, Long>, CustomTopicRepository {

default Topic getById(Long id) {
return findById(id).orElseThrow(() -> new CustomException(RESOURCE_NOT_FOUND));
}

@Query(value = "SELECT * FROM topic WHERE is_exposed='true' ORDER BY RAND() LIMIT 5", nativeQuery = true)
List<Topic> get5TopicsRandomly();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.listywave.topic.application.domain.Topic;
import com.listywave.topic.application.service.dto.ExposedTopicFindResponse;
import com.listywave.topic.application.service.dto.ExposedTopicFindResponse.TopicDto;
import com.listywave.topic.application.service.dto.RecommendTopicFindResponse;
import com.listywave.topic.application.service.dto.TopicCreateRequest;
import com.listywave.topic.application.service.dto.TopicFindResponse;
import java.util.List;
Expand Down Expand Up @@ -91,22 +92,7 @@ class 사용자용_토픽_조회 {
@Test
void cursorId가_null이고_size가_10일_때_노출이_승인된_토픽을_조회한다() {
// given
List<Topic> topics = List.of(
new Topic(dh, MUSIC, new ListTitle("1"), new ListDescription("1"), false, true),
new Topic(dh, MUSIC, new ListTitle("2"), new ListDescription("2"), false, true),
new Topic(dh, MUSIC, new ListTitle("3"), new ListDescription("3"), false, true),
new Topic(dh, MUSIC, new ListTitle("4"), new ListDescription("4"), false, true),
new Topic(dh, MUSIC, new ListTitle("5"), new ListDescription("5"), false, true),
new Topic(dh, MUSIC, new ListTitle("6"), new ListDescription("6"), false, true),
new Topic(dh, MUSIC, new ListTitle("7"), new ListDescription("7"), false, true),
new Topic(dh, MUSIC, new ListTitle("8"), new ListDescription("8"), false, true),
new Topic(dh, MUSIC, new ListTitle("9"), new ListDescription("9"), false, true),
new Topic(dh, MUSIC, new ListTitle("10"), new ListDescription("10"), false, true),
new Topic(dh, MUSIC, new ListTitle("11"), new ListDescription("11"), false, true),
new Topic(dh, MUSIC, new ListTitle("12"), new ListDescription("12"), false, true),
new Topic(dh, MUSIC, new ListTitle("13"), new ListDescription("13"), false, true)
);
topicRepository.saveAll(topics);
save10TopicsAllExposed();

// when
int size = 10;
Expand All @@ -125,9 +111,7 @@ class 사용자용_토픽_조회 {
);
}

@Test
void cursorId가_뒤에서_다섯_번째고_size가_5일_때_노출이_승인된_토픽을_조회한다() {
// given
private List<Topic> save10TopicsAllExposed() {
List<Topic> topics = List.of(
new Topic(dh, MUSIC, new ListTitle("1"), new ListDescription("1"), false, true),
new Topic(dh, MUSIC, new ListTitle("2"), new ListDescription("2"), false, true),
Expand All @@ -145,6 +129,14 @@ class 사용자용_토픽_조회 {
);
topicRepository.saveAll(topics);

return topics;
}

@Test
void cursorId가_뒤에서_다섯_번째고_size가_5일_때_노출이_승인된_토픽을_조회한다() {
// given
List<Topic> topics = save10TopicsAllExposed();

// when
long cursorId = topics.get(8).getId();
ExposedTopicFindResponse result = topicService.findAllExposed(cursorId, 5);
Expand All @@ -162,6 +154,44 @@ class 사용자용_토픽_조회 {
);

}

@Test
// @Repeat(10)
void 홈_화면에서_추천_토픽을_조회한다() {
// given
List<Topic> topics = List.of(
new Topic(dh, MUSIC, new ListTitle("1"), new ListDescription("1"), false, true), // O
new Topic(dh, MUSIC, new ListTitle("2"), new ListDescription("2"), false, false),
new Topic(dh, MUSIC, new ListTitle("3"), new ListDescription("3"), false, true), // O
new Topic(dh, MUSIC, new ListTitle("4"), new ListDescription("4"), false, false),
new Topic(dh, MUSIC, new ListTitle("5"), new ListDescription("5"), false, true), // O
new Topic(dh, MUSIC, new ListTitle("6"), new ListDescription("6"), false, false),
new Topic(dh, MUSIC, new ListTitle("7"), new ListDescription("7"), false, true), // O
new Topic(dh, MUSIC, new ListTitle("8"), new ListDescription("8"), false, false),
new Topic(dh, MUSIC, new ListTitle("9"), new ListDescription("9"), false, true), // O
new Topic(dh, MUSIC, new ListTitle("10"), new ListDescription("10"), false, false),
new Topic(dh, MUSIC, new ListTitle("11"), new ListDescription("11"), false, true), // O
new Topic(dh, MUSIC, new ListTitle("12"), new ListDescription("12"), false, false),
new Topic(dh, MUSIC, new ListTitle("13"), new ListDescription("13"), false, true) // O
);
topicRepository.saveAll(topics);

// when
List<RecommendTopicFindResponse> result = topicService.findRecommendTopics();

// then
assertAll(
() -> {
List<String> titles = result.stream()
.map(RecommendTopicFindResponse::title)
.toList();

assertThat(titles).hasSizeLessThanOrEqualTo(5);
assertThat(titles).containsAnyOf("1", "3", "5", "7", "9", "11", "13");
assertThat(titles).doesNotContainAnyElementsOf(List.of("2", "4", "6", "8", "10", "12"));
}
);
}
}

@Nested
Expand Down

0 comments on commit f66e606

Please sign in to comment.