Compare commits
No commits in common. "83028f7817f81b202a64e4f0fe6a4caa924f9f53" and "70d179555786c4b6dbd681fd8979484ff1bd585e" have entirely different histories.
83028f7817
...
70d1795557
|
@ -11,7 +11,6 @@ import javax.persistence.Id
|
||||||
import javax.persistence.JoinColumn
|
import javax.persistence.JoinColumn
|
||||||
import javax.persistence.ManyToOne
|
import javax.persistence.ManyToOne
|
||||||
import javax.persistence.PrePersist
|
import javax.persistence.PrePersist
|
||||||
import javax.persistence.PreUpdate
|
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
class SeriesKeyword {
|
class SeriesKeyword {
|
||||||
|
@ -20,7 +19,6 @@ class SeriesKeyword {
|
||||||
var id: Long? = null
|
var id: Long? = null
|
||||||
|
|
||||||
var createdAt: LocalDateTime? = null
|
var createdAt: LocalDateTime? = null
|
||||||
var updatedAt: LocalDateTime? = null
|
|
||||||
|
|
||||||
@ManyToOne(fetch = FetchType.LAZY)
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
@JoinColumn(name = "series_id", nullable = false)
|
@JoinColumn(name = "series_id", nullable = false)
|
||||||
|
@ -30,16 +28,8 @@ class SeriesKeyword {
|
||||||
@JoinColumn(name = "keyword_id", nullable = false)
|
@JoinColumn(name = "keyword_id", nullable = false)
|
||||||
var keyword: HashTag? = null
|
var keyword: HashTag? = null
|
||||||
|
|
||||||
var isActive: Boolean = true
|
|
||||||
|
|
||||||
@PrePersist
|
@PrePersist
|
||||||
fun prePersist() {
|
fun prePersist() {
|
||||||
createdAt = LocalDateTime.now()
|
createdAt = LocalDateTime.now()
|
||||||
updatedAt = LocalDateTime.now()
|
|
||||||
}
|
|
||||||
|
|
||||||
@PreUpdate
|
|
||||||
fun preUpdate() {
|
|
||||||
updatedAt = LocalDateTime.now()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package kr.co.vividnext.sodalive.marketing
|
package kr.co.vividnext.sodalive.marketing
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
|
||||||
import org.springframework.web.bind.annotation.PostMapping
|
import org.springframework.web.bind.annotation.PostMapping
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
import org.springframework.web.bind.annotation.RequestMapping
|
||||||
|
@ -13,7 +12,6 @@ class AdTrackingController(private val service: AdTrackingService) {
|
||||||
fun trackingAppLaunch(
|
fun trackingAppLaunch(
|
||||||
@RequestBody request: AdTrackingAppLaunchRequest
|
@RequestBody request: AdTrackingAppLaunchRequest
|
||||||
) = run {
|
) = run {
|
||||||
ApiResponse.ok(
|
|
||||||
service.saveTrackingHistory(
|
service.saveTrackingHistory(
|
||||||
pid = request.pid,
|
pid = request.pid,
|
||||||
type = AdTrackingHistoryType.APP_LAUNCH,
|
type = AdTrackingHistoryType.APP_LAUNCH,
|
||||||
|
@ -21,6 +19,5 @@ class AdTrackingController(private val service: AdTrackingService) {
|
||||||
price = null,
|
price = null,
|
||||||
locale = null
|
locale = null
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.search
|
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.common.ApiResponse
|
|
||||||
import kr.co.vividnext.sodalive.common.SodaException
|
|
||||||
import kr.co.vividnext.sodalive.content.ContentType
|
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
|
||||||
import org.springframework.data.domain.Pageable
|
|
||||||
import org.springframework.security.core.annotation.AuthenticationPrincipal
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
|
||||||
import org.springframework.web.bind.annotation.RequestMapping
|
|
||||||
import org.springframework.web.bind.annotation.RequestParam
|
|
||||||
import org.springframework.web.bind.annotation.RestController
|
|
||||||
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/search")
|
|
||||||
class SearchController(private val service: SearchService) {
|
|
||||||
@GetMapping
|
|
||||||
fun searchUnified(
|
|
||||||
@RequestParam keyword: String,
|
|
||||||
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
|
|
||||||
@RequestParam("contentType", required = false) contentType: ContentType? = null,
|
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?
|
|
||||||
) = run {
|
|
||||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
ApiResponse.ok(
|
|
||||||
service.searchUnified(
|
|
||||||
keyword,
|
|
||||||
isAdultContentVisible = isAdultContentVisible ?: true,
|
|
||||||
contentType = contentType ?: ContentType.ALL,
|
|
||||||
member = member
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/creators")
|
|
||||||
fun searchCreatorList(
|
|
||||||
@RequestParam keyword: String,
|
|
||||||
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
|
|
||||||
@RequestParam("contentType", required = false) contentType: ContentType? = null,
|
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
|
|
||||||
pageable: Pageable
|
|
||||||
) = run {
|
|
||||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
ApiResponse.ok(
|
|
||||||
service.searchCreatorList(
|
|
||||||
keyword,
|
|
||||||
isAdultContentVisible = isAdultContentVisible ?: true,
|
|
||||||
contentType = contentType ?: ContentType.ALL,
|
|
||||||
member = member,
|
|
||||||
offset = pageable.offset,
|
|
||||||
limit = pageable.pageSize.toLong()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/contents")
|
|
||||||
fun searchContentList(
|
|
||||||
@RequestParam keyword: String,
|
|
||||||
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
|
|
||||||
@RequestParam("contentType", required = false) contentType: ContentType? = null,
|
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
|
|
||||||
pageable: Pageable
|
|
||||||
) = run {
|
|
||||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
ApiResponse.ok(
|
|
||||||
service.searchContentList(
|
|
||||||
keyword,
|
|
||||||
isAdultContentVisible = isAdultContentVisible ?: true,
|
|
||||||
contentType = contentType ?: ContentType.ALL,
|
|
||||||
member = member,
|
|
||||||
offset = pageable.offset,
|
|
||||||
limit = pageable.pageSize.toLong()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/series")
|
|
||||||
fun searchSeriesList(
|
|
||||||
@RequestParam keyword: String,
|
|
||||||
@RequestParam("isAdultContentVisible", required = false) isAdultContentVisible: Boolean? = null,
|
|
||||||
@RequestParam("contentType", required = false) contentType: ContentType? = null,
|
|
||||||
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member?,
|
|
||||||
pageable: Pageable
|
|
||||||
) = run {
|
|
||||||
if (member == null) throw SodaException("로그인 정보를 확인해주세요.")
|
|
||||||
ApiResponse.ok(
|
|
||||||
service.searchSeriesList(
|
|
||||||
keyword,
|
|
||||||
isAdultContentVisible = isAdultContentVisible ?: true,
|
|
||||||
contentType = contentType ?: ContentType.ALL,
|
|
||||||
member = member,
|
|
||||||
offset = pageable.offset,
|
|
||||||
limit = pageable.pageSize.toLong()
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,354 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.search
|
|
||||||
|
|
||||||
import com.querydsl.jpa.impl.JPAQueryFactory
|
|
||||||
import kr.co.vividnext.sodalive.admin.content.series.genre.QSeriesGenre.seriesGenre
|
|
||||||
import kr.co.vividnext.sodalive.content.ContentType
|
|
||||||
import kr.co.vividnext.sodalive.content.QAudioContent.audioContent
|
|
||||||
import kr.co.vividnext.sodalive.content.hashtag.QAudioContentHashTag.audioContentHashTag
|
|
||||||
import kr.co.vividnext.sodalive.content.hashtag.QHashTag.hashTag
|
|
||||||
import kr.co.vividnext.sodalive.content.theme.QAudioContentTheme.audioContentTheme
|
|
||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeries.series
|
|
||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.QSeriesContent.seriesContent
|
|
||||||
import kr.co.vividnext.sodalive.creator.admin.content.series.keyword.QSeriesKeyword.seriesKeyword
|
|
||||||
import kr.co.vividnext.sodalive.member.MemberRole
|
|
||||||
import kr.co.vividnext.sodalive.member.QMember.member
|
|
||||||
import kr.co.vividnext.sodalive.member.block.QBlockMember.blockMember
|
|
||||||
import kr.co.vividnext.sodalive.member.tag.QCreatorTag.creatorTag
|
|
||||||
import kr.co.vividnext.sodalive.member.tag.QMemberCreatorTag.memberCreatorTag
|
|
||||||
import org.springframework.beans.factory.annotation.Value
|
|
||||||
import org.springframework.stereotype.Repository
|
|
||||||
|
|
||||||
@Repository
|
|
||||||
class SearchRepository(
|
|
||||||
private val queryFactory: JPAQueryFactory,
|
|
||||||
|
|
||||||
@Value("\${cloud.aws.cloud-front.host}")
|
|
||||||
private val imageHost: String
|
|
||||||
) {
|
|
||||||
fun searchCreatorTotalCount(
|
|
||||||
keyword: String,
|
|
||||||
memberId: Long
|
|
||||||
): Int {
|
|
||||||
val blockMemberCondition = blockMember.member.id.eq(member.id)
|
|
||||||
.and(blockMember.isActive.isTrue)
|
|
||||||
.and(blockMember.blockedMember.id.eq(memberId))
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(member.id)
|
|
||||||
.from(member)
|
|
||||||
.leftJoin(memberCreatorTag).on(memberCreatorTag.member.id.eq(member.id))
|
|
||||||
.leftJoin(creatorTag).on(memberCreatorTag.tag.id.eq(creatorTag.id))
|
|
||||||
.leftJoin(blockMember).on(blockMemberCondition)
|
|
||||||
.where(
|
|
||||||
member.isActive.isTrue
|
|
||||||
.and(member.role.eq(MemberRole.CREATOR))
|
|
||||||
.and(creatorTag.isActive.isTrue.or(creatorTag.id.isNull))
|
|
||||||
.and(
|
|
||||||
member.nickname.containsIgnoreCase(keyword)
|
|
||||||
.or(member.introduce.containsIgnoreCase(keyword))
|
|
||||||
.or(creatorTag.tag.containsIgnoreCase(keyword))
|
|
||||||
)
|
|
||||||
.and(blockMember.id.isNull)
|
|
||||||
)
|
|
||||||
.groupBy(member.id)
|
|
||||||
.fetch()
|
|
||||||
.size
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchCreatorList(
|
|
||||||
keyword: String,
|
|
||||||
memberId: Long,
|
|
||||||
offset: Long,
|
|
||||||
limit: Long
|
|
||||||
): List<SearchResponseItem> {
|
|
||||||
val blockMemberCondition = blockMember.member.id.eq(member.id)
|
|
||||||
.and(blockMember.isActive.isTrue)
|
|
||||||
.and(blockMember.blockedMember.id.eq(memberId))
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(
|
|
||||||
QSearchResponseItem(
|
|
||||||
member.id,
|
|
||||||
member.profileImage.prepend("/").prepend(imageHost),
|
|
||||||
member.nickname,
|
|
||||||
member.nickname
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.from(member)
|
|
||||||
.leftJoin(memberCreatorTag).on(memberCreatorTag.member.id.eq(member.id))
|
|
||||||
.leftJoin(creatorTag).on(memberCreatorTag.tag.id.eq(creatorTag.id))
|
|
||||||
.leftJoin(blockMember).on(blockMemberCondition)
|
|
||||||
.where(
|
|
||||||
member.isActive.isTrue
|
|
||||||
.and(member.role.eq(MemberRole.CREATOR))
|
|
||||||
.and(creatorTag.isActive.isTrue.or(creatorTag.id.isNull))
|
|
||||||
.and(
|
|
||||||
member.nickname.containsIgnoreCase(keyword)
|
|
||||||
.or(member.introduce.containsIgnoreCase(keyword))
|
|
||||||
.or(creatorTag.tag.containsIgnoreCase(keyword))
|
|
||||||
)
|
|
||||||
.and(blockMember.id.isNull)
|
|
||||||
)
|
|
||||||
.groupBy(member.id)
|
|
||||||
.orderBy(member.id.desc())
|
|
||||||
.offset(offset)
|
|
||||||
.limit(limit)
|
|
||||||
.fetch()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchContentTotalCount(
|
|
||||||
keyword: String,
|
|
||||||
memberId: Long,
|
|
||||||
isAdult: Boolean,
|
|
||||||
contentType: ContentType
|
|
||||||
): Int {
|
|
||||||
val blockMemberCondition = blockMember.member.id.eq(member.id)
|
|
||||||
.and(blockMember.isActive.isTrue)
|
|
||||||
.and(blockMember.blockedMember.id.eq(memberId))
|
|
||||||
|
|
||||||
var where = audioContent.member.isActive.isTrue
|
|
||||||
.and(audioContent.member.role.eq(MemberRole.CREATOR))
|
|
||||||
.and(audioContent.isActive.isTrue)
|
|
||||||
.and(audioContent.limited.isNull)
|
|
||||||
.and(audioContent.duration.isNotNull)
|
|
||||||
.and(
|
|
||||||
audioContent.title.containsIgnoreCase(keyword)
|
|
||||||
.or(audioContent.detail.containsIgnoreCase(keyword))
|
|
||||||
.or(audioContent.theme.theme.containsIgnoreCase(keyword))
|
|
||||||
.or(hashTag.tag.containsIgnoreCase(keyword).and(audioContentHashTag.isActive.isTrue))
|
|
||||||
|
|
||||||
)
|
|
||||||
.and(blockMember.id.isNull)
|
|
||||||
|
|
||||||
if (!isAdult) {
|
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
|
||||||
} else {
|
|
||||||
if (contentType != ContentType.ALL) {
|
|
||||||
where = where.and(
|
|
||||||
audioContent.member.isNull.or(
|
|
||||||
audioContent.member.auth.gender.eq(
|
|
||||||
if (contentType == ContentType.MALE) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(audioContent.id)
|
|
||||||
.from(audioContent)
|
|
||||||
.innerJoin(audioContent.member, member)
|
|
||||||
.leftJoin(audioContentTheme).on(audioContentTheme.id.eq(audioContent.theme.id))
|
|
||||||
.leftJoin(audioContentHashTag).on(audioContentHashTag.audioContent.id.eq(audioContent.id))
|
|
||||||
.leftJoin(hashTag).on(audioContentHashTag.hashTag.id.eq(hashTag.id))
|
|
||||||
.leftJoin(blockMember).on(blockMemberCondition)
|
|
||||||
.where(where)
|
|
||||||
.groupBy(audioContent.id)
|
|
||||||
.fetch()
|
|
||||||
.size
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchContentList(
|
|
||||||
keyword: String,
|
|
||||||
memberId: Long,
|
|
||||||
isAdult: Boolean,
|
|
||||||
contentType: ContentType,
|
|
||||||
offset: Long,
|
|
||||||
limit: Long
|
|
||||||
): List<SearchResponseItem> {
|
|
||||||
val blockMemberCondition = blockMember.member.id.eq(member.id)
|
|
||||||
.and(blockMember.isActive.isTrue)
|
|
||||||
.and(blockMember.blockedMember.id.eq(memberId))
|
|
||||||
|
|
||||||
var where = audioContent.member.isActive.isTrue
|
|
||||||
.and(audioContent.member.role.eq(MemberRole.CREATOR))
|
|
||||||
.and(audioContent.isActive.isTrue)
|
|
||||||
.and(audioContent.limited.isNull)
|
|
||||||
.and(audioContent.duration.isNotNull)
|
|
||||||
.and(
|
|
||||||
audioContent.title.containsIgnoreCase(keyword)
|
|
||||||
.or(audioContent.detail.containsIgnoreCase(keyword))
|
|
||||||
.or(audioContent.theme.theme.containsIgnoreCase(keyword))
|
|
||||||
.or(hashTag.tag.containsIgnoreCase(keyword).and(audioContentHashTag.isActive.isTrue))
|
|
||||||
|
|
||||||
)
|
|
||||||
.and(blockMember.id.isNull)
|
|
||||||
|
|
||||||
if (!isAdult) {
|
|
||||||
where = where.and(audioContent.isAdult.isFalse)
|
|
||||||
} else {
|
|
||||||
if (contentType != ContentType.ALL) {
|
|
||||||
where = where.and(
|
|
||||||
audioContent.member.isNull.or(
|
|
||||||
audioContent.member.auth.gender.eq(
|
|
||||||
if (contentType == ContentType.MALE) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(
|
|
||||||
QSearchResponseItem(
|
|
||||||
audioContent.id,
|
|
||||||
audioContent.coverImage.prepend("/").prepend(imageHost),
|
|
||||||
audioContent.title,
|
|
||||||
audioContent.member.nickname
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.from(audioContent)
|
|
||||||
.innerJoin(audioContent.member, member)
|
|
||||||
.leftJoin(audioContentTheme).on(audioContentTheme.id.eq(audioContent.theme.id))
|
|
||||||
.leftJoin(audioContentHashTag).on(audioContentHashTag.audioContent.id.eq(audioContent.id))
|
|
||||||
.leftJoin(hashTag).on(audioContentHashTag.hashTag.id.eq(hashTag.id))
|
|
||||||
.leftJoin(blockMember).on(blockMemberCondition)
|
|
||||||
.where(where)
|
|
||||||
.groupBy(audioContent.id)
|
|
||||||
.orderBy(audioContent.id.desc())
|
|
||||||
.offset(offset)
|
|
||||||
.limit(limit)
|
|
||||||
.fetch()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchSeriesTotalCount(
|
|
||||||
keyword: String,
|
|
||||||
memberId: Long,
|
|
||||||
isAdult: Boolean,
|
|
||||||
contentType: ContentType
|
|
||||||
): Int {
|
|
||||||
val blockMemberCondition = blockMember.member.id.eq(member.id)
|
|
||||||
.and(blockMember.isActive.isTrue)
|
|
||||||
.and(blockMember.blockedMember.id.eq(memberId))
|
|
||||||
|
|
||||||
var where = series.isActive.isTrue
|
|
||||||
.and(audioContent.isActive.isTrue)
|
|
||||||
.and(member.isActive.isTrue)
|
|
||||||
.and(member.isNotNull)
|
|
||||||
.and(member.role.eq(MemberRole.CREATOR))
|
|
||||||
.and(audioContent.duration.isNotNull)
|
|
||||||
.and(audioContent.limited.isNull)
|
|
||||||
.and(
|
|
||||||
series.title.containsIgnoreCase(keyword)
|
|
||||||
.or(series.introduction.containsIgnoreCase(keyword))
|
|
||||||
.or(seriesGenre.genre.containsIgnoreCase(keyword))
|
|
||||||
.or(hashTag.tag.containsIgnoreCase(keyword).and(seriesKeyword.isActive.isTrue))
|
|
||||||
)
|
|
||||||
.and(blockMember.id.isNull)
|
|
||||||
|
|
||||||
if (!isAdult) {
|
|
||||||
where = where
|
|
||||||
.and(series.isAdult.isFalse)
|
|
||||||
.and(audioContent.isAdult.isFalse)
|
|
||||||
} else {
|
|
||||||
if (contentType != ContentType.ALL) {
|
|
||||||
where = where.and(
|
|
||||||
audioContent.member.isNull.or(
|
|
||||||
audioContent.member.auth.gender.eq(
|
|
||||||
if (contentType == ContentType.MALE) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(series.id)
|
|
||||||
.from(seriesContent)
|
|
||||||
.innerJoin(seriesContent.series, series)
|
|
||||||
.innerJoin(seriesContent.content, audioContent)
|
|
||||||
.innerJoin(series.member, member)
|
|
||||||
.leftJoin(seriesGenre).on(seriesGenre.id.eq(series.genre.id))
|
|
||||||
.leftJoin(seriesKeyword).on(seriesKeyword.series.id.eq(series.id))
|
|
||||||
.leftJoin(hashTag).on(hashTag.id.eq(seriesKeyword.keyword.id))
|
|
||||||
.leftJoin(blockMember).on(blockMemberCondition)
|
|
||||||
.where(where)
|
|
||||||
.groupBy(series.id, series.orders)
|
|
||||||
.fetch()
|
|
||||||
.size
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchSeriesList(
|
|
||||||
keyword: String,
|
|
||||||
memberId: Long,
|
|
||||||
isAdult: Boolean,
|
|
||||||
contentType: ContentType,
|
|
||||||
offset: Long,
|
|
||||||
limit: Long
|
|
||||||
): List<SearchResponseItem> {
|
|
||||||
val blockMemberCondition = blockMember.member.id.eq(member.id)
|
|
||||||
.and(blockMember.isActive.isTrue)
|
|
||||||
.and(blockMember.blockedMember.id.eq(memberId))
|
|
||||||
|
|
||||||
var where = series.isActive.isTrue
|
|
||||||
.and(audioContent.isActive.isTrue)
|
|
||||||
.and(member.isActive.isTrue)
|
|
||||||
.and(member.isNotNull)
|
|
||||||
.and(member.role.eq(MemberRole.CREATOR))
|
|
||||||
.and(audioContent.duration.isNotNull)
|
|
||||||
.and(audioContent.limited.isNull)
|
|
||||||
.and(
|
|
||||||
series.title.containsIgnoreCase(keyword)
|
|
||||||
.or(series.introduction.containsIgnoreCase(keyword))
|
|
||||||
.or(seriesGenre.genre.containsIgnoreCase(keyword))
|
|
||||||
.or(hashTag.tag.containsIgnoreCase(keyword).and(seriesKeyword.isActive.isTrue))
|
|
||||||
)
|
|
||||||
.and(blockMember.id.isNull)
|
|
||||||
|
|
||||||
if (!isAdult) {
|
|
||||||
where = where
|
|
||||||
.and(series.isAdult.isFalse)
|
|
||||||
.and(audioContent.isAdult.isFalse)
|
|
||||||
} else {
|
|
||||||
if (contentType != ContentType.ALL) {
|
|
||||||
where = where.and(
|
|
||||||
audioContent.member.isNull.or(
|
|
||||||
audioContent.member.auth.gender.eq(
|
|
||||||
if (contentType == ContentType.MALE) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
1
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return queryFactory
|
|
||||||
.select(
|
|
||||||
QSearchResponseItem(
|
|
||||||
series.id,
|
|
||||||
series.coverImage.prepend("/").prepend(imageHost),
|
|
||||||
series.title,
|
|
||||||
series.member.nickname
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.from(seriesContent)
|
|
||||||
.innerJoin(seriesContent.series, series)
|
|
||||||
.innerJoin(seriesContent.content, audioContent)
|
|
||||||
.innerJoin(series.member, member)
|
|
||||||
.leftJoin(seriesGenre).on(seriesGenre.id.eq(series.genre.id))
|
|
||||||
.leftJoin(seriesKeyword).on(seriesKeyword.series.id.eq(series.id))
|
|
||||||
.leftJoin(hashTag).on(hashTag.id.eq(seriesKeyword.keyword.id))
|
|
||||||
.leftJoin(blockMember).on(blockMemberCondition)
|
|
||||||
.where(where)
|
|
||||||
.groupBy(series.id, series.orders)
|
|
||||||
.orderBy(series.orders.asc())
|
|
||||||
.offset(offset)
|
|
||||||
.limit(limit)
|
|
||||||
.fetch()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.search
|
|
||||||
|
|
||||||
import com.querydsl.core.annotations.QueryProjection
|
|
||||||
|
|
||||||
data class SearchUnifiedResponse(
|
|
||||||
val creatorList: List<SearchResponseItem>,
|
|
||||||
val contentList: List<SearchResponseItem>,
|
|
||||||
val seriesList: List<SearchResponseItem>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class SearchResponse(
|
|
||||||
val totalCount: Int,
|
|
||||||
val items: List<SearchResponseItem>
|
|
||||||
)
|
|
||||||
|
|
||||||
data class SearchResponseItem @QueryProjection constructor(
|
|
||||||
val id: Long,
|
|
||||||
val imageUrl: String,
|
|
||||||
val title: String,
|
|
||||||
val nickname: String
|
|
||||||
) {
|
|
||||||
var type: SearchResponseType = SearchResponseType.CREATOR
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class SearchResponseType {
|
|
||||||
CREATOR, CONTENT, SERIES
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
package kr.co.vividnext.sodalive.search
|
|
||||||
|
|
||||||
import kr.co.vividnext.sodalive.content.ContentType
|
|
||||||
import kr.co.vividnext.sodalive.member.Member
|
|
||||||
import org.springframework.stereotype.Service
|
|
||||||
|
|
||||||
@Service
|
|
||||||
class SearchService(private val repository: SearchRepository) {
|
|
||||||
fun searchUnified(
|
|
||||||
keyword: String,
|
|
||||||
isAdultContentVisible: Boolean,
|
|
||||||
contentType: ContentType,
|
|
||||||
member: Member
|
|
||||||
): SearchUnifiedResponse {
|
|
||||||
val isAdult = member.auth != null && isAdultContentVisible
|
|
||||||
|
|
||||||
val creatorList = repository.searchCreatorList(
|
|
||||||
keyword = keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
offset = 0,
|
|
||||||
limit = 3
|
|
||||||
)
|
|
||||||
.map {
|
|
||||||
it.type = SearchResponseType.CREATOR
|
|
||||||
it
|
|
||||||
}
|
|
||||||
|
|
||||||
val contentList = repository.searchContentList(
|
|
||||||
keyword = keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
isAdult = isAdult,
|
|
||||||
contentType = contentType,
|
|
||||||
offset = 0,
|
|
||||||
limit = 3
|
|
||||||
)
|
|
||||||
.map {
|
|
||||||
it.type = SearchResponseType.CONTENT
|
|
||||||
it
|
|
||||||
}
|
|
||||||
|
|
||||||
val seriesList = repository.searchSeriesList(
|
|
||||||
keyword = keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
isAdult = isAdult,
|
|
||||||
contentType = contentType,
|
|
||||||
offset = 0,
|
|
||||||
limit = 3
|
|
||||||
)
|
|
||||||
.map {
|
|
||||||
it.type = SearchResponseType.SERIES
|
|
||||||
it
|
|
||||||
}
|
|
||||||
|
|
||||||
return SearchUnifiedResponse(
|
|
||||||
creatorList = creatorList,
|
|
||||||
contentList = contentList,
|
|
||||||
seriesList = seriesList
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchCreatorList(
|
|
||||||
keyword: String,
|
|
||||||
isAdultContentVisible: Boolean,
|
|
||||||
contentType: ContentType,
|
|
||||||
member: Member,
|
|
||||||
offset: Long,
|
|
||||||
limit: Long
|
|
||||||
): SearchResponse {
|
|
||||||
val totalCount = repository.searchCreatorTotalCount(keyword, memberId = member.id!!)
|
|
||||||
val items = repository.searchCreatorList(
|
|
||||||
keyword = keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
offset = offset,
|
|
||||||
limit = limit
|
|
||||||
)
|
|
||||||
.map {
|
|
||||||
it.type = SearchResponseType.CREATOR
|
|
||||||
it
|
|
||||||
}
|
|
||||||
|
|
||||||
return SearchResponse(totalCount, items)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchContentList(
|
|
||||||
keyword: String,
|
|
||||||
isAdultContentVisible: Boolean,
|
|
||||||
contentType: ContentType,
|
|
||||||
member: Member,
|
|
||||||
offset: Long,
|
|
||||||
limit: Long
|
|
||||||
): SearchResponse {
|
|
||||||
val isAdult = member.auth != null && isAdultContentVisible
|
|
||||||
|
|
||||||
val totalCount = repository.searchContentTotalCount(
|
|
||||||
keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
isAdult = isAdult,
|
|
||||||
contentType = contentType
|
|
||||||
)
|
|
||||||
|
|
||||||
val items = repository.searchContentList(
|
|
||||||
keyword = keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
isAdult = isAdult,
|
|
||||||
contentType = contentType,
|
|
||||||
offset = offset,
|
|
||||||
limit = limit
|
|
||||||
)
|
|
||||||
.map {
|
|
||||||
it.type = SearchResponseType.CONTENT
|
|
||||||
it
|
|
||||||
}
|
|
||||||
|
|
||||||
return SearchResponse(totalCount, items)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchSeriesList(
|
|
||||||
keyword: String,
|
|
||||||
isAdultContentVisible: Boolean,
|
|
||||||
contentType: ContentType,
|
|
||||||
member: Member,
|
|
||||||
offset: Long,
|
|
||||||
limit: Long
|
|
||||||
): SearchResponse {
|
|
||||||
val isAdult = member.auth != null && isAdultContentVisible
|
|
||||||
|
|
||||||
val totalCount = repository.searchSeriesTotalCount(
|
|
||||||
keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
isAdult = isAdult,
|
|
||||||
contentType = contentType
|
|
||||||
)
|
|
||||||
|
|
||||||
val items = repository.searchSeriesList(
|
|
||||||
keyword = keyword,
|
|
||||||
memberId = member.id!!,
|
|
||||||
isAdult = isAdult,
|
|
||||||
contentType = contentType,
|
|
||||||
offset = offset,
|
|
||||||
limit = limit
|
|
||||||
)
|
|
||||||
.map {
|
|
||||||
it.type = SearchResponseType.SERIES
|
|
||||||
it
|
|
||||||
}
|
|
||||||
|
|
||||||
return SearchResponse(totalCount, items)
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue