Skip to content

Commit

Permalink
feat: Question isSearchable 추가 (#82)
Browse files Browse the repository at this point in the history
* feat: question 테이블 isSearchable 추가하는 쿼리문 추가

* feat: isSearchable 지정 로직 추가

* feat: isSearchable 업데이트 로직 반영

* feat: isSearchable=true인 question들만 노출되도록 where문 추가

* refactor: origin content 비교 if문 메서드 분리, bundleRepository findAll -> search로 메서드명 변경

* chore

* fix: 원본 콘텐트 비교 로직 버그 수정

* refactor: isEqualToOriginContent

* fix: findNotSearchableFirstOneByOriginId custom 레포에서 구현
  • Loading branch information
annahxxl authored Mar 14, 2024
1 parent ff9c5e4 commit d511254
Show file tree
Hide file tree
Showing 10 changed files with 56 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ interface BundleCustomRepository {

fun count(condition: BundleSearchCondition): Long

fun findAll(condition: BundleSearchCondition, pageable: Pageable): List<Bundle>
fun search(condition: BundleSearchCondition, pageable: Pageable): List<Bundle>

fun findAllByMemberId(memberId: Long, condition: BundleGetCondition): List<Bundle>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class BundleCustomRepositoryImpl(private val queryFactory: JPAQueryFactory) : Bu
return query.fetchOne()!!
}

override fun findAll(condition: BundleSearchCondition, pageable: Pageable): List<Bundle> {
override fun search(condition: BundleSearchCondition, pageable: Pageable): List<Bundle> {
val query = queryFactory
.selectFrom(bundle)
.leftJoin(bundle.bundleTags, bundleTag).fetchJoin()
Expand Down
15 changes: 15 additions & 0 deletions data/src/main/kotlin/com/kw/data/domain/question/Question.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class Question(
content: String,
answer: String? = null,
answerShareType: AnswerShareType,
isSearchable: Boolean,
originId: Long? = null,
bundle: Bundle,
member: Member
Expand All @@ -35,6 +36,15 @@ class Question(
var answerShareType: AnswerShareType = answerShareType
protected set

/**
* originId가 null인 경우 원본이므로 isSearchable=true 여야 한다.
* 복제본은 isSearchable=false이되, 원본과 content가 달라질 경우, isSearchable=true로 변경되어야 한다.
* 원본이 삭제될 경우, 복제본 중 isSearchable=false이면서 가장 먼저 생성된 복제본은 isSearchable=true로 변경되어야 한다.
*/
@Column(name = "is_searchable", nullable = false, updatable = true)
var isSearchable: Boolean = isSearchable
protected set

@Column(name = "origin_id", nullable = true, updatable = true)
val originId: Long? = originId

Expand Down Expand Up @@ -81,6 +91,10 @@ class Question(
this.answerShareType = answerShareType
}

fun updateSearchableStatus(isSearchable: Boolean) {
this.isSearchable = isSearchable
}

fun updateQuestionTags(questionTags: List<QuestionTag>) {
if (questionTags.size > 3) {
throw IllegalArgumentException("태그는 최대 3개까지 지정 가능합니다.")
Expand All @@ -94,6 +108,7 @@ class Question(
content = this.content,
answer = if (this.answerShareType === AnswerShareType.PUBLIC) this.answer else null,
answerShareType = AnswerShareType.PUBLIC,
isSearchable = false,
originId = this.id,
bundle = bundle,
member = member
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ interface QuestionCustomRepository {

fun findAllWithTagsByBundleId(bundleId: Long, showOnlyMyQuestions: Boolean?, memberId: Long?): List<Question>

fun findNotSearchableFirstOneByOriginId(originId: Long): Question?
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class QuestionCustomRepositoryImpl(val jpaQueryFactory: JPAQueryFactory) : Quest
.selectFrom(question)
.leftJoin(question.questionTags, questionTag).fetchJoin()
.where(
question.isSearchable.isTrue,
keyword?.let { CustomFunction.match(question.content, keyword) }
)
.orderBy(
Expand Down Expand Up @@ -53,6 +54,7 @@ class QuestionCustomRepositoryImpl(val jpaQueryFactory: JPAQueryFactory) : Quest
.select(question.count())
.from(question)
.where(
question.isSearchable.isTrue,
keyword?.let { CustomFunction.match(question.content, keyword) }
)

Expand Down Expand Up @@ -92,4 +94,15 @@ class QuestionCustomRepositoryImpl(val jpaQueryFactory: JPAQueryFactory) : Quest
return query.fetch()
}

override fun findNotSearchableFirstOneByOriginId(originId: Long): Question? {
return jpaQueryFactory
.selectFrom(question)
.where(
question.originId.eq(originId),
question.isSearchable.isFalse
)
.orderBy(question.id.asc())
.limit(1)
.fetchOne()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface QuestionRepository : JpaRepository<Question, Long>, QuestionCustomRepo
fun findAllByBundleId(bundleId: Long): List<Question>

@Query("SELECT q FROM Question q LEFT JOIN FETCH q.questionTags qt LEFT JOIN FETCH qt.tag WHERE q.id IN :ids")
fun findAllWithTagsByIdIn(ids: List<Long>): List<Question>
fun findAllWithTagsByIdIn(@Param("ids") ids: List<Long>): List<Question>

@Query("SELECT q FROM Question q LEFT JOIN FETCH q.questionTags qt LEFT JOIN FETCH qt.tag WHERE q.bundle.id = :bundleId")
fun findAllWithTagsByBundleId(@Param("bundleId") bundleId: Long): List<Question>
Expand Down
1 change: 1 addition & 0 deletions data/src/main/resources/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ CREATE TABLE IF NOT EXISTS question
answer VARCHAR(1500) NULL,
answer_share_type VARCHAR(10) NOT NULL,
share_count BIGINT UNSIGNED NOT NULL DEFAULT 0,
is_searchable BOOLEAN NOT NULL,
origin_id BIGINT UNSIGNED NULL,
bundle_id BIGINT UNSIGNED NOT NULL,
member_id BIGINT UNSIGNED NOT NULL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class BundleService(
pageCondition: PageCondition
): PageResponse<BundleResponse> {
val pageable = PageRequest.of(pageCondition.page.minus(1), pageCondition.size)
val bundles = bundleRepository.findAll(searchCondition, pageable)
val bundles = bundleRepository.search(searchCondition, pageable)
.map { BundleResponse.from(it) }
return PageResponse.from(
PageableExecutionUtils.getPage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ data class QuestionCreateRequest(
content = content,
answer = answer,
answerShareType = answerShareType,
isSearchable = true,
bundle = bundle,
member = member
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import com.kw.data.domain.tag.Tag
import com.kw.data.domain.tag.repository.TagRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.*

@Service
@Transactional
Expand Down Expand Up @@ -59,7 +60,15 @@ class QuestionService(
throw ApiException(ApiErrorCode.FORBIDDEN)
}

request.content?.let { question.updateContent(it) }
request.content?.let {
question.originId?.let { originId ->
val origin = questionRepository.findById(originId)
if (!isEqualToOriginContent(origin, it)) {
question.updateSearchableStatus(true)
}
}
question.updateContent(it)
}
request.answer?.let { question.updateAnswer(it) }
request.answerShareType?.let { question.updateAnswerShareStatus(it) }
request.tagIds?.let { it ->
Expand All @@ -76,6 +85,13 @@ class QuestionService(
throw ApiException(ApiErrorCode.FORBIDDEN)
}

if (question.originId == null) {
val copiedQuestion = questionRepository.findNotSearchableFirstOneByOriginId(id)
copiedQuestion?.let {
copiedQuestion.updateSearchableStatus(true)
}
}

questionRepository.delete(question)
}

Expand Down Expand Up @@ -117,4 +133,8 @@ class QuestionService(
return questionRepository.findById(id)
.orElseThrow { ApiException(ApiErrorCode.NOT_FOUND_QUESTION) }
}

private fun isEqualToOriginContent(origin: Optional<Question>, content: String): Boolean {
return origin.isPresent && origin.get().content == content
}
}

0 comments on commit d511254

Please sign in to comment.