Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
feat: ✨ 일기 내용 검색 기능 구현 (#53)
Browse files Browse the repository at this point in the history
* Initial commit

* Feat/#1 oauth2login (#3)

* feat: User 엔터티 생성

* feat: jwt 버전 11->12, JWTUtil 생성

* feat: JWTFilter(JwtAuthenticationFilter) 등록

* feat: kakao 로그인 구현

* docs: swagger 태그(Authorization) 추가 (#5)

* feat: User 엔터티 생성

* feat: jwt 버전 11->12, JWTUtil 생성

* feat: JWTFilter(JwtAuthenticationFilter) 등록

* feat: kakao 로그인 구현

* docs: swagger 태그(Authorization) 추가

* feat: accesstoken 테스트를 위한 test login 생성 (#9)

* feat: User 엔티티에 상속 (#12)

* feat: BaseEntity 생성

* feat: User 엔티티에 상속

* feat: 일기 생성 기능 구현 (#14)

* feat: accesstoken 테스트를 위한 test login 생성

* feat: 일기 생성 기능 구현

* hotfix: ci 에러 수정 (#16)

* feat: accesstoken 테스트를 위한 test login 생성

* feat: 일기 생성 기능 구현

* hotfix: ci 에러 수정

* fix: OIDC 카카오 로그인 nullPointerException 해결

* feat: 닉네임 설정 기능 구현 (#21)

* feat: 일기 수정 기능 구현 (#25)

* feat: 일기에 감정 컬럼 추가

* feat: 일기 수정 기능 구현

* feat: 일기 삭제 기능 구현 (#27)

* feat: 일기에 감정 컬럼 추가

* feat: 일기 수정 기능 구현

* feat: 일기 삭제 기능 구현

* feat: 일기 감정 분석 기능 구현 (#31)

* feat: 감정 저장 기능 구현 (#33)

* feat: 일기 감정 분석 기능 구현

* feat: 감정 저장 기능 구현

* fix: 🐛 감정 저장 안되던 오류 수정 (#35)

* feat: 일기 감정 분석 기능 구현

* feat: 감정 저장 기능 구현

* fix: 🐛 감정 저장 안되던 오류 수정

* hotfix: 🚑 서버 꺼짐 현상 해결 (#37)

* feat: 일기 감정 분석 기능 구현

* feat: 감정 저장 기능 구현

* fix: 🐛 감정 저장 안되던 오류 수정

* hotfix: 🚑 서버 꺼짐 현상 해결

* feat: ✨ 홈 화면 조회 기능 구현 (#41)

* feat: ✨ 회원가입 완료 여부 필드 추가 (#44)

* feat: ✨ 일기 상세 조회 구현 (#47)

* feat: ✨ 기간 별 감정 통계 조회 기능 구현 (#50)

* feat: ✨ 일기 내용 검색 기능 구현 (#52)
  • Loading branch information
LEEJaeHyeok97 authored Jul 28, 2024
1 parent 469858f commit 420a4c2
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import com.aidiary.domain.diary.domain.Diary;
import com.aidiary.domain.diary.domain.repository.DiaryRepository;
import com.aidiary.domain.diary.dto.*;
import com.aidiary.domain.diary.dto.condition.DiariesSearchCondition;
import com.aidiary.domain.user.domain.User;
import com.aidiary.domain.user.domain.repository.UserRepository;
import com.aidiary.global.config.security.token.UserPrincipal;
import com.aidiary.global.payload.Message;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand Down Expand Up @@ -113,4 +116,11 @@ public DiaryDetailsRes viewDiary(UserPrincipal userPrincipal, Long diaryId) thro
return diaryDetailsRes;

}

public Page<SearchDiariesRes> findDiariesByContent(UserPrincipal userPrincipal, DiariesSearchCondition diariesSearchCondition, Pageable pageable) {
User user = userRepository.findById(userPrincipal.getId())
.orElseThrow(EntityNotFoundException::new);

return diaryRepository.findDiaries(user, diariesSearchCondition, pageable);
}
}
1 change: 0 additions & 1 deletion src/main/java/com/aidiary/domain/diary/domain/Diary.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ public class Diary extends BaseEntity {
@JoinColumn(name = "user_id")
private User user;

@Lob
@Column(name = "content", columnDefinition = "TEXT")
private String content;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.aidiary.domain.diary.domain.repository;

import com.aidiary.domain.diary.dto.SearchDiariesRes;
import com.aidiary.domain.diary.dto.condition.DiariesSearchCondition;
import com.aidiary.domain.emotion.dto.EmotionStatRes;
import com.aidiary.domain.home.dto.HomeViewRes;
import com.aidiary.domain.user.domain.User;
import com.aidiary.global.config.security.token.UserPrincipal;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.time.LocalDate;
import java.util.List;
Expand All @@ -14,4 +19,6 @@ public interface DiaryQueryDslRepository {
int findConsecutiveWritingDays(Long userId);

EmotionStatRes findEmotionsCountBetweenStartDateAndEndDate(Long id, LocalDate startDate, LocalDate endDate);

Page<SearchDiariesRes> findDiaries(User user, DiariesSearchCondition diariesSearchCondition, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
package com.aidiary.domain.diary.domain.repository;

import com.aidiary.domain.diary.domain.QDiary;
import com.aidiary.domain.diary.dto.QSearchDiariesRes;
import com.aidiary.domain.diary.dto.SearchDiariesRes;
import com.aidiary.domain.diary.dto.condition.DiariesSearchCondition;
import com.aidiary.domain.emotion.dto.EmotionStatRes;
import com.aidiary.domain.emotion.dto.QEmotionStatRes;
import com.aidiary.domain.home.dto.HomeViewRes;
import com.aidiary.domain.home.dto.QHomeViewRes;
import com.aidiary.domain.user.domain.User;
import com.aidiary.global.config.security.token.UserPrincipal;
import com.querydsl.core.types.dsl.CaseBuilder;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.core.types.dsl.NumberTemplate;
import com.querydsl.core.types.Ops;
import com.querydsl.core.types.dsl.*;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;

import java.time.LocalDate;
Expand Down Expand Up @@ -106,5 +112,48 @@ public EmotionStatRes findEmotionsCountBetweenStartDateAndEndDate(Long userId, L
.fetchOne();
}

@Override
public Page<SearchDiariesRes> findDiaries(User user, DiariesSearchCondition diariesSearchCondition, Pageable pageable) {
String content = diariesSearchCondition.content();

List<SearchDiariesRes> results;

JPAQuery<Long> countQuery;


results = queryFactory
.select(new QSearchDiariesRes(
getExcerpt(diary.content, content),
diary.diaryEntryDate,
Expressions.constant("test")
))
.from(diary)
.where(diary.content.contains(content),
equalsUser(user))
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.orderBy(diary.diaryEntryDate.desc())
.fetch();

countQuery = queryFactory
.select(diary.count())
.from(diary)
.where(diary.content.contains(content));


return PageableExecutionUtils.getPage(results, pageable, countQuery::fetchOne);
}

public BooleanExpression equalsUser(User user) {
return user != null ? diary.user.eq(user) : null;
}

private StringTemplate getExcerpt(StringPath content, String keyword) {
return Expressions.stringTemplate(
"concat(substring({0}, greatest(1, locate({1}, {0}) - 10), least(locate({1}, {0}) - greatest(1, locate({1}, {0}) - 10), 10)), {1}, substring({0}, locate({1}, {0}) + length({1}), 10))",
content, Expressions.constant(keyword)
);
}


}
21 changes: 21 additions & 0 deletions src/main/java/com/aidiary/domain/diary/dto/SearchDiariesRes.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.aidiary.domain.diary.dto;

import com.querydsl.core.annotations.QueryProjection;
import lombok.Builder;

import java.time.LocalDate;

@Builder
public record SearchDiariesRes(
String previewContent,
LocalDate diaryEntryDate,
String surroundingText
) {

@QueryProjection
public SearchDiariesRes(String previewContent, LocalDate diaryEntryDate, String surroundingText) {
this.previewContent = previewContent;
this.diaryEntryDate = diaryEntryDate;
this.surroundingText = surroundingText;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.aidiary.domain.diary.dto.condition;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;

@Builder
public record DiariesSearchCondition(

@Schema(type = "string", example = "용산 엑스포에 놀러갔던 날", description = "content로 일기 내용을 검색합니다.")
String content
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.aidiary.domain.diary.application.DiaryService;
import com.aidiary.domain.diary.dto.*;
import com.aidiary.domain.diary.dto.condition.DiariesSearchCondition;
import com.aidiary.global.config.security.token.CurrentUser;
import com.aidiary.global.config.security.token.UserPrincipal;
import com.aidiary.global.payload.ErrorResponse;
Expand All @@ -16,6 +17,8 @@
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.nio.file.AccessDeniedException;
Expand Down Expand Up @@ -80,4 +83,18 @@ public ResponseCustom<Message> deleteDiary(
) {
return ResponseCustom.OK(diaryService.removeDiary(userPrincipal, id));
}

@Operation(summary = "일기 검색(내용) 조회", description = "일기를 검색 조건에 따라 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "일기 조회 성공", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = SearchDiariesRes.class))}),
@ApiResponse(responseCode = "400", description = "일기 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}),
})
@GetMapping("/contentSearch")
public ResponseCustom<Page<SearchDiariesRes>> findDiaries(
@Parameter(description = "AccessToken 을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal,
@ModelAttribute DiariesSearchCondition diariesSearchCondition,
@Parameter(description = "조회 할 페이지와 페이지 크기를 입력해주세요.") Pageable pageable
) {
return ResponseCustom.OK(diaryService.findDiariesByContent(userPrincipal, diariesSearchCondition, pageable));
}
}

0 comments on commit 420a4c2

Please sign in to comment.