test #436
@@ -686,17 +686,10 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
and ccc.created_at >= :windowStart
|
and ccc.created_at >= :windowStart
|
||||||
and ccc.created_at < :windowEndExclusive
|
and ccc.created_at < :windowEndExclusive
|
||||||
group by ccc.creator_community_id
|
group by ccc.creator_community_id
|
||||||
),
|
|
||||||
follower_stats as (
|
|
||||||
select cf.creator_id as creator_id, count(distinct cf.id) as follower_count
|
|
||||||
from creator_following cf
|
|
||||||
where cf.is_active = true
|
|
||||||
group by cf.creator_id
|
|
||||||
)
|
)
|
||||||
select cc.id as target_id,
|
select cc.id as target_id,
|
||||||
((coalesce(ls.like_count, 0) * ${RecommendationScoreSpec.COMMUNITY_LIKE_WEIGHT} +
|
((coalesce(ls.like_count, 0) * ${RecommendationScoreSpec.COMMUNITY_LIKE_WEIGHT} +
|
||||||
(case when cc.is_comment_available = true then coalesce(cs.comment_count, 0) else 0 end) * ${RecommendationScoreSpec.COMMUNITY_COMMENT_WEIGHT} +
|
(case when cc.is_comment_available = true then coalesce(cs.comment_count, 0) else 0 end) * ${RecommendationScoreSpec.COMMUNITY_COMMENT_WEIGHT}) *
|
||||||
coalesce(fs.follower_count, 0) * ${RecommendationScoreSpec.COMMUNITY_FOLLOWER_WEIGHT}) *
|
|
||||||
case
|
case
|
||||||
when cd.debut_at >= :boost10Start then ${RecommendationScoreSpec.COMMUNITY_NEW_BOOST_10_DAYS}
|
when cd.debut_at >= :boost10Start then ${RecommendationScoreSpec.COMMUNITY_NEW_BOOST_10_DAYS}
|
||||||
when cd.debut_at >= :boost20Start then ${RecommendationScoreSpec.COMMUNITY_NEW_BOOST_20_DAYS}
|
when cd.debut_at >= :boost20Start then ${RecommendationScoreSpec.COMMUNITY_NEW_BOOST_20_DAYS}
|
||||||
@@ -709,7 +702,6 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
join creator_debut cd on cd.creator_id = cc.member_id
|
join creator_debut cd on cd.creator_id = cc.member_id
|
||||||
left join like_stats ls on ls.community_id = cc.id
|
left join like_stats ls on ls.community_id = cc.id
|
||||||
left join comment_stats cs on cs.community_id = cc.id
|
left join comment_stats cs on cs.community_id = cc.id
|
||||||
left join follower_stats fs on fs.creator_id = cc.member_id
|
|
||||||
where cc.is_active = true
|
where cc.is_active = true
|
||||||
and m.is_active = true
|
and m.is_active = true
|
||||||
and cc.price <= 0
|
and cc.price <= 0
|
||||||
@@ -719,7 +711,6 @@ class DefaultHomeRecommendationQueryRepository(
|
|||||||
and (
|
and (
|
||||||
coalesce(ls.like_count, 0) > 0
|
coalesce(ls.like_count, 0) > 0
|
||||||
or (cc.is_comment_available = true and coalesce(cs.comment_count, 0) > 0)
|
or (cc.is_comment_available = true and coalesce(cs.comment_count, 0) > 0)
|
||||||
or coalesce(fs.follower_count, 0) > 0
|
|
||||||
)
|
)
|
||||||
order by score desc, random_tie_breaker asc
|
order by score desc, random_tie_breaker asc
|
||||||
limit :limit
|
limit :limit
|
||||||
|
|||||||
@@ -936,7 +936,7 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("인기 커뮤니티 스냅샷은 좋아요 댓글 팔로워 수를 distinct로 집계하고 댓글 불가 게시글은 댓글 수 0으로 계산한다")
|
@DisplayName("인기 커뮤니티 스냅샷은 좋아요와 댓글 수를 distinct로 집계하고 follower-only 게시글은 제외한다")
|
||||||
fun shouldFindPopularCommunitySnapshotsWithDistinctCounts() {
|
fun shouldFindPopularCommunitySnapshotsWithDistinctCounts() {
|
||||||
val windowStart = LocalDateTime.of(2026, 5, 23, 0, 0)
|
val windowStart = LocalDateTime.of(2026, 5, 23, 0, 0)
|
||||||
val snapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
|
val snapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
|
||||||
@@ -977,17 +977,10 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
val expectedPostScore = scorePolicy.calculateCommunityScore(
|
val expectedPostScore = scorePolicy.calculateCommunityScore(
|
||||||
likeCount = 2,
|
likeCount = 2,
|
||||||
commentCount = 2,
|
commentCount = 2,
|
||||||
followerCount = 2,
|
|
||||||
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(LocalDateTime.of(2026, 4, 1, 12, 0), snapshotAt)
|
|
||||||
)
|
|
||||||
val expectedCommentDisabledScore = scorePolicy.calculateCommunityScore(
|
|
||||||
likeCount = 0,
|
|
||||||
commentCount = 0,
|
|
||||||
followerCount = 2,
|
|
||||||
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(LocalDateTime.of(2026, 4, 1, 12, 0), snapshotAt)
|
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(LocalDateTime.of(2026, 4, 1, 12, 0), snapshotAt)
|
||||||
)
|
)
|
||||||
assertEquals(expectedPostScore, snapshots[post.id]!!.score, 0.0001)
|
assertEquals(expectedPostScore, snapshots[post.id]!!.score, 0.0001)
|
||||||
assertEquals(expectedCommentDisabledScore, snapshots[commentDisabledPost.id]!!.score, 0.0001)
|
assertEquals(false, snapshots.containsKey(commentDisabledPost.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -1040,7 +1033,6 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
val expectedScore = scorePolicy.calculateCommunityScore(
|
val expectedScore = scorePolicy.calculateCommunityScore(
|
||||||
likeCount = 1,
|
likeCount = 1,
|
||||||
commentCount = 0,
|
commentCount = 0,
|
||||||
followerCount = 0,
|
|
||||||
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(LocalDateTime.of(2026, 5, 20, 0, 0), snapshotAt)
|
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(LocalDateTime.of(2026, 5, 20, 0, 0), snapshotAt)
|
||||||
)
|
)
|
||||||
assertEquals(1, snapshots.size)
|
assertEquals(1, snapshots.size)
|
||||||
@@ -1050,17 +1042,19 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("인기 커뮤니티 스냅샷은 좋아요 댓글 팔로워가 모두 0인 게시글을 제외한다")
|
@DisplayName("인기 커뮤니티 스냅샷은 좋아요와 댓글이 모두 0인 게시글을 제외한다")
|
||||||
fun shouldExcludeZeroMetricPopularCommunitySnapshots() {
|
fun shouldExcludeZeroMetricPopularCommunitySnapshots() {
|
||||||
val windowStart = LocalDateTime.of(2026, 5, 23, 0, 0)
|
val windowStart = LocalDateTime.of(2026, 5, 23, 0, 0)
|
||||||
val snapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
|
val snapshotAt = LocalDateTime.of(2026, 5, 29, 23, 59, 59)
|
||||||
val windowEndExclusive = snapshotAt.plusSeconds(1)
|
val windowEndExclusive = snapshotAt.plusSeconds(1)
|
||||||
val creator = saveMember("zero-community-creator", MemberRole.CREATOR)
|
val creator = saveMember("zero-community-creator", MemberRole.CREATOR)
|
||||||
val liker = saveMember("zero-community-liker", MemberRole.USER)
|
val liker = saveMember("zero-community-liker", MemberRole.USER)
|
||||||
|
val follower = saveMember("zero-community-follower", MemberRole.USER)
|
||||||
saveLiveRoom(creator, LocalDateTime.of(2026, 5, 10, 12, 0), channelName = "zero-community-live")
|
saveLiveRoom(creator, LocalDateTime.of(2026, 5, 10, 12, 0), channelName = "zero-community-live")
|
||||||
val zeroPost = saveCommunity(creator, isCommentAvailable = true)
|
val zeroPost = saveCommunity(creator, isCommentAvailable = true)
|
||||||
val scoredPost = saveCommunity(creator, isCommentAvailable = true)
|
val scoredPost = saveCommunity(creator, isCommentAvailable = true)
|
||||||
val like = saveCommunityLike(liker, scoredPost, isActive = true)
|
val like = saveCommunityLike(liker, scoredPost, isActive = true)
|
||||||
|
saveFollowing(follower, creator, isActive = true)
|
||||||
updateCreatedAt("CreatorCommunity", zeroPost.id!!, windowStart.plusDays(1))
|
updateCreatedAt("CreatorCommunity", zeroPost.id!!, windowStart.plusDays(1))
|
||||||
updateCreatedAt("CreatorCommunity", scoredPost.id!!, windowStart.plusDays(1))
|
updateCreatedAt("CreatorCommunity", scoredPost.id!!, windowStart.plusDays(1))
|
||||||
updateCreatedAt("CreatorCommunityLike", like.id!!, windowStart.plusDays(1))
|
updateCreatedAt("CreatorCommunityLike", like.id!!, windowStart.plusDays(1))
|
||||||
@@ -1170,7 +1164,6 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
val expectedCommunityScore = scorePolicy.calculateCommunityScore(
|
val expectedCommunityScore = scorePolicy.calculateCommunityScore(
|
||||||
likeCount = 1,
|
likeCount = 1,
|
||||||
commentCount = 0,
|
commentCount = 0,
|
||||||
followerCount = 0,
|
|
||||||
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(firstLiveAt, snapshotAt)
|
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(firstLiveAt, snapshotAt)
|
||||||
)
|
)
|
||||||
assertEquals(expectedCheerScore, cheerSnapshot.score, 0.0001)
|
assertEquals(expectedCheerScore, cheerSnapshot.score, 0.0001)
|
||||||
@@ -1217,7 +1210,6 @@ class DefaultHomeRecommendationQueryRepositoryTest @Autowired constructor(
|
|||||||
val expectedCommunityScore = scorePolicy.calculateCommunityScore(
|
val expectedCommunityScore = scorePolicy.calculateCommunityScore(
|
||||||
likeCount = 1,
|
likeCount = 1,
|
||||||
commentCount = 0,
|
commentCount = 0,
|
||||||
followerCount = 0,
|
|
||||||
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(contentDebutAt, snapshotAt)
|
newBoost = scorePolicy.calculateCommunityCreatorNewBoost(contentDebutAt, snapshotAt)
|
||||||
)
|
)
|
||||||
assertEquals(expectedCheerScore, cheerSnapshot.score, 0.0001)
|
assertEquals(expectedCheerScore, cheerSnapshot.score, 0.0001)
|
||||||
|
|||||||
Reference in New Issue
Block a user