차단 사용자 제외를 조회 쿼리로 통합

홈, 추천 채널, 랭킹 조회에서 차단 사용자 제외를
애플리케이션 필터링 대신 DB 쿼리로 처리한다.
콘텐츠/랭킹/추천 조회 API에 memberId 인자를 전달한다.
This commit is contained in:
2026-02-12 16:01:53 +09:00
parent 7afbf1bff8
commit 232d97e37e
7 changed files with 110 additions and 75 deletions

View File

@@ -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)

View File

@@ -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,