차단 사용자 제외를 조회 쿼리로 통합
홈, 추천 채널, 랭킹 조회에서 차단 사용자 제외를 애플리케이션 필터링 대신 DB 쿼리로 처리한다. 콘텐츠/랭킹/추천 조회 API에 memberId 인자를 전달한다.
This commit is contained in:
@@ -22,7 +22,6 @@ import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomService
|
||||
import kr.co.vividnext.sodalive.live.room.LiveRoomStatus
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberService
|
||||
import kr.co.vividnext.sodalive.query.recommend.RecommendChannelQueryService
|
||||
import kr.co.vividnext.sodalive.rank.ContentRankingSortType
|
||||
import kr.co.vividnext.sodalive.rank.RankingRepository
|
||||
@@ -37,7 +36,6 @@ import java.time.temporal.TemporalAdjusters
|
||||
|
||||
@Service
|
||||
class HomeService(
|
||||
private val memberService: MemberService,
|
||||
private val liveRoomService: LiveRoomService,
|
||||
private val auditionService: AuditionService,
|
||||
private val seriesService: ContentSeriesService,
|
||||
@@ -85,14 +83,7 @@ class HomeService(
|
||||
)
|
||||
|
||||
val creatorRanking = rankingRepository
|
||||
.getCreatorRankings()
|
||||
.filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.id!!)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
.getCreatorRankings(memberId = memberId)
|
||||
.map {
|
||||
val followerCount = explorerQueryRepository.getNotificationUserIds(it.id!!).size
|
||||
val follow = if (memberId != null) {
|
||||
@@ -111,17 +102,12 @@ class HomeService(
|
||||
)
|
||||
|
||||
val latestContentList = contentService.getLatestContentByTheme(
|
||||
memberId = memberId,
|
||||
theme = latestContentThemeList,
|
||||
contentType = contentType,
|
||||
isFree = false,
|
||||
isAdult = isAdult
|
||||
).filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.creatorId)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val translatedLatestContentList = getTranslatedContentList(contentList = latestContentList)
|
||||
|
||||
@@ -237,6 +223,7 @@ class HomeService(
|
||||
}
|
||||
|
||||
val freeContentList = contentService.getLatestContentByTheme(
|
||||
memberId = memberId,
|
||||
theme = contentThemeService.getActiveThemeOfContent(
|
||||
isAdult = isAdult,
|
||||
isFree = true,
|
||||
@@ -246,31 +233,20 @@ class HomeService(
|
||||
isFree = true,
|
||||
isAdult = isAdult,
|
||||
orderByRandom = true
|
||||
).filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.creatorId)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val translatedFreeContentList = getTranslatedContentList(contentList = freeContentList)
|
||||
|
||||
// 포인트 사용가능 콘텐츠 리스트 - 랜덤으로 가져오기 (DB에서 isPointAvailable 조건 적용)
|
||||
val pointAvailableContentList = contentService.getLatestContentByTheme(
|
||||
memberId = memberId,
|
||||
theme = emptyList(),
|
||||
contentType = contentType,
|
||||
isFree = false,
|
||||
isAdult = isAdult,
|
||||
orderByRandom = true,
|
||||
isPointAvailableOnly = true
|
||||
).filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.creatorId)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
val translatedPointAvailableContentList = getTranslatedContentList(contentList = pointAvailableContentList)
|
||||
|
||||
@@ -326,17 +302,12 @@ class HomeService(
|
||||
}
|
||||
|
||||
val contentList = contentService.getLatestContentByTheme(
|
||||
memberId = memberId,
|
||||
theme = themeList,
|
||||
contentType = contentType,
|
||||
isFree = false,
|
||||
isAdult = isAdult
|
||||
).filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.creatorId)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
return getTranslatedContentList(contentList = contentList)
|
||||
}
|
||||
@@ -428,6 +399,7 @@ class HomeService(
|
||||
while (attempt < RECOMMEND_MAX_ATTEMPTS && result.size < RECOMMEND_TARGET_SIZE) {
|
||||
attempt += 1
|
||||
val batch = contentService.getLatestContentByTheme(
|
||||
memberId = memberId,
|
||||
theme = emptyList(), // 특정 테마에 종속되지 않도록 전체에서 랜덤 조회
|
||||
contentType = contentType,
|
||||
offset = 0,
|
||||
@@ -435,13 +407,7 @@ class HomeService(
|
||||
isFree = false,
|
||||
isAdult = isAdult,
|
||||
orderByRandom = true
|
||||
).filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.creatorId)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
for (item in batch) {
|
||||
if (result.size >= RECOMMEND_TARGET_SIZE) break
|
||||
|
||||
@@ -178,6 +178,7 @@ interface AudioContentQueryRepository {
|
||||
fun findContentIdAndHashTagId(contentId: Long, hashTagId: Int): AudioContentHashTag?
|
||||
|
||||
fun getLatestContentByTheme(
|
||||
memberId: Long? = null,
|
||||
theme: List<String>,
|
||||
contentType: ContentType,
|
||||
offset: Long,
|
||||
@@ -1319,6 +1320,7 @@ class AudioContentQueryRepositoryImpl(
|
||||
}
|
||||
|
||||
override fun getLatestContentByTheme(
|
||||
memberId: Long?,
|
||||
theme: List<String>,
|
||||
contentType: ContentType,
|
||||
offset: Long,
|
||||
@@ -1329,6 +1331,14 @@ class AudioContentQueryRepositoryImpl(
|
||||
orderByRandom: Boolean,
|
||||
isPointAvailableOnly: Boolean
|
||||
): List<AudioContentMainItem> {
|
||||
val blockMemberCondition = if (memberId != null) {
|
||||
blockMember.member.id.eq(member.id)
|
||||
.and(blockMember.isActive.isTrue)
|
||||
.and(blockMember.blockedMember.id.eq(memberId))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
var where = audioContent.isActive.isTrue
|
||||
.and(audioContent.duration.isNotNull)
|
||||
.and(
|
||||
@@ -1366,6 +1376,26 @@ class AudioContentQueryRepositoryImpl(
|
||||
where = where.and(audioContent.isPointAvailable.isTrue)
|
||||
}
|
||||
|
||||
var select = queryFactory
|
||||
.select(
|
||||
QAudioContentMainItem(
|
||||
audioContent.id,
|
||||
member.id,
|
||||
audioContent.title,
|
||||
audioContent.coverImage.prepend("/").prepend(imageHost),
|
||||
member.nickname,
|
||||
audioContent.isPointAvailable
|
||||
)
|
||||
)
|
||||
.from(audioContent)
|
||||
.innerJoin(audioContent.member, member)
|
||||
.innerJoin(audioContent.theme, audioContentTheme)
|
||||
|
||||
if (memberId != null) {
|
||||
where = where.and(blockMember.id.isNull)
|
||||
select = select.leftJoin(blockMember).on(blockMemberCondition)
|
||||
}
|
||||
|
||||
val orderBy = if (orderByRandom) {
|
||||
Expressions.numberTemplate(Double::class.java, "function('rand')").asc()
|
||||
} else {
|
||||
@@ -1387,20 +1417,7 @@ class AudioContentQueryRepositoryImpl(
|
||||
}
|
||||
}
|
||||
|
||||
return queryFactory
|
||||
.select(
|
||||
QAudioContentMainItem(
|
||||
audioContent.id,
|
||||
member.id,
|
||||
audioContent.title,
|
||||
audioContent.coverImage.prepend("/").prepend(imageHost),
|
||||
member.nickname,
|
||||
audioContent.isPointAvailable
|
||||
)
|
||||
)
|
||||
.from(audioContent)
|
||||
.innerJoin(audioContent.member, member)
|
||||
.innerJoin(audioContent.theme, audioContentTheme)
|
||||
return select
|
||||
.where(where)
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
|
||||
@@ -1198,6 +1198,7 @@ class AudioContentService(
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
fun getLatestContentByTheme(
|
||||
memberId: Long? = null,
|
||||
theme: List<String>,
|
||||
contentType: ContentType,
|
||||
offset: Long = 0,
|
||||
@@ -1221,6 +1222,7 @@ class AudioContentService(
|
||||
)
|
||||
|
||||
val contentList = repository.getLatestContentByTheme(
|
||||
memberId = memberId,
|
||||
theme = normalizedTheme,
|
||||
contentType = contentType,
|
||||
offset = offset,
|
||||
|
||||
@@ -9,6 +9,7 @@ import kr.co.vividnext.sodalive.content.like.QAudioContentLike.audioContentLike
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import kr.co.vividnext.sodalive.member.QMember.member
|
||||
import kr.co.vividnext.sodalive.member.auth.QAuth.auth
|
||||
import kr.co.vividnext.sodalive.member.block.QBlockMember.blockMember
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
@@ -19,7 +20,19 @@ class RecommendChannelQueryRepository(
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val imageHost: String
|
||||
) {
|
||||
fun getRecommendChannelList(isAdult: Boolean, contentType: ContentType): List<RecommendChannelResponse> {
|
||||
fun getRecommendChannelList(
|
||||
memberId: Long?,
|
||||
isAdult: Boolean,
|
||||
contentType: ContentType
|
||||
): List<RecommendChannelResponse> {
|
||||
val blockMemberCondition = if (memberId != null) {
|
||||
blockMember.member.id.eq(member.id)
|
||||
.and(blockMember.isActive.isTrue)
|
||||
.and(blockMember.blockedMember.id.eq(memberId))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
var where = member.role.eq(MemberRole.CREATOR)
|
||||
.and(audioContent.isActive.isTrue)
|
||||
|
||||
@@ -39,7 +52,7 @@ class RecommendChannelQueryRepository(
|
||||
}
|
||||
}
|
||||
|
||||
return queryFactory
|
||||
var select = queryFactory
|
||||
.select(
|
||||
QRecommendChannelResponse(
|
||||
member.id,
|
||||
@@ -52,6 +65,13 @@ class RecommendChannelQueryRepository(
|
||||
.from(member)
|
||||
.innerJoin(auth).on(auth.member.id.eq(member.id))
|
||||
.innerJoin(audioContent).on(audioContent.member.id.eq(member.id))
|
||||
|
||||
if (memberId != null) {
|
||||
where = where.and(blockMember.id.isNull)
|
||||
select = select.leftJoin(blockMember).on(blockMemberCondition)
|
||||
}
|
||||
|
||||
return select
|
||||
.where(where)
|
||||
.groupBy(member.id)
|
||||
.having(audioContent.id.count().goe(3))
|
||||
@@ -60,14 +80,26 @@ class RecommendChannelQueryRepository(
|
||||
.fetch()
|
||||
}
|
||||
|
||||
fun getContentsByCreatorIdLikeDesc(creatorId: Long, isAdult: Boolean): List<RecommendChannelContentItem> {
|
||||
fun getContentsByCreatorIdLikeDesc(
|
||||
creatorId: Long,
|
||||
memberId: Long?,
|
||||
isAdult: Boolean
|
||||
): List<RecommendChannelContentItem> {
|
||||
val blockMemberCondition = if (memberId != null) {
|
||||
blockMember.member.id.eq(audioContent.member.id)
|
||||
.and(blockMember.isActive.isTrue)
|
||||
.and(blockMember.blockedMember.id.eq(memberId))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
var where = audioContent.member.id.eq(creatorId)
|
||||
|
||||
if (!isAdult) {
|
||||
where = where.and(audioContent.isAdult.isFalse)
|
||||
}
|
||||
|
||||
return queryFactory
|
||||
var select = queryFactory
|
||||
.select(
|
||||
QRecommendChannelContentItem(
|
||||
audioContent.id,
|
||||
@@ -88,6 +120,13 @@ class RecommendChannelQueryRepository(
|
||||
audioContentComment.audioContent.id.eq(audioContent.id)
|
||||
.and(audioContentComment.isActive.isTrue)
|
||||
)
|
||||
|
||||
if (memberId != null) {
|
||||
where = where.and(blockMember.id.isNull)
|
||||
select = select.leftJoin(blockMember).on(blockMemberCondition)
|
||||
}
|
||||
|
||||
return select
|
||||
.where(where)
|
||||
.groupBy(audioContent.id)
|
||||
.orderBy(audioContentLike.id.countDistinct().desc())
|
||||
|
||||
@@ -18,6 +18,7 @@ class RecommendChannelQueryService(private val repository: RecommendChannelQuery
|
||||
contentType: ContentType
|
||||
): List<RecommendChannelResponse> {
|
||||
val recommendChannelList = repository.getRecommendChannelList(
|
||||
memberId = memberId,
|
||||
isAdult = isAdult,
|
||||
contentType = contentType
|
||||
)
|
||||
@@ -25,6 +26,7 @@ class RecommendChannelQueryService(private val repository: RecommendChannelQuery
|
||||
return recommendChannelList.map {
|
||||
it.contentList = repository.getContentsByCreatorIdLikeDesc(
|
||||
creatorId = it.channelId,
|
||||
memberId = memberId,
|
||||
isAdult = isAdult
|
||||
)
|
||||
|
||||
|
||||
@@ -33,11 +33,29 @@ class RankingRepository(
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
private val imageHost: String
|
||||
) {
|
||||
fun getCreatorRankings(): List<Member> {
|
||||
return queryFactory
|
||||
fun getCreatorRankings(memberId: Long? = null): List<Member> {
|
||||
val blockMemberCondition = if (memberId != null) {
|
||||
blockMember.member.id.eq(member.id)
|
||||
.and(blockMember.isActive.isTrue)
|
||||
.and(blockMember.blockedMember.id.eq(memberId))
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
var select = queryFactory
|
||||
.select(member)
|
||||
.from(creatorRanking)
|
||||
.innerJoin(creatorRanking.member, member)
|
||||
|
||||
if (memberId != null) {
|
||||
select = select.leftJoin(blockMember).on(blockMemberCondition)
|
||||
}
|
||||
|
||||
if (memberId != null) {
|
||||
select = select.where(blockMember.id.isNull)
|
||||
}
|
||||
|
||||
return select
|
||||
.orderBy(creatorRanking.ranking.asc())
|
||||
.fetch()
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import kr.co.vividnext.sodalive.creator.admin.content.series.Series
|
||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesPublishedDaysOfWeek
|
||||
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesState
|
||||
import kr.co.vividnext.sodalive.explorer.GetExplorerSectionResponse
|
||||
import kr.co.vividnext.sodalive.member.MemberService
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.stereotype.Service
|
||||
import java.time.LocalDateTime
|
||||
@@ -17,7 +16,6 @@ import java.time.LocalDateTime
|
||||
@Service
|
||||
class RankingService(
|
||||
private val repository: RankingRepository,
|
||||
private val memberService: MemberService,
|
||||
private val seriesContentRepository: ContentSeriesContentRepository,
|
||||
|
||||
@Value("\${cloud.aws.cloud-front.host}")
|
||||
@@ -25,14 +23,7 @@ class RankingService(
|
||||
) {
|
||||
fun getCreatorRanking(memberId: Long?, rankingDate: String): GetExplorerSectionResponse {
|
||||
val creatorRankings = repository
|
||||
.getCreatorRankings()
|
||||
.filter {
|
||||
if (memberId != null) {
|
||||
!memberService.isBlocked(blockedMemberId = memberId, memberId = it.id!!)
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
.getCreatorRankings(memberId = memberId)
|
||||
.map { it.toExplorerSectionCreator(imageHost) }
|
||||
|
||||
return GetExplorerSectionResponse(
|
||||
|
||||
Reference in New Issue
Block a user