From 76d7c9c7ad40d2b422177c3dfe97b77a7eee9d17 Mon Sep 17 00:00:00 2001 From: dong3058 Date: Thu, 4 Sep 2025 17:27:31 +0900 Subject: [PATCH 1/5] elasticsearch start --- build.gradle | 6 + .../admin/document/ContentDocument.java | 68 ++++++ .../admin/document/ImprovementDocument.java | 64 ++++++ .../admin/document/InquiryDocument.java | 55 +++++ .../admin/dto/request/ContentRequestDto.java | 5 + .../admin/dto/request/ImproveRequestDto.java | 4 +- .../dto/response/ResponseContentDto.java | 1 - .../AdminImprovementSearchRepo.java | 100 ++++++++- .../repository/ContentSearchRepository.java | 146 +++++++++++- .../admin/repository/InquirySearchRepo.java | 99 +++++++++ .../simpleRepo/ElasticContentRepository.java | 7 + .../simpleRepo/ElasticImproverRepository.java | 7 + .../simpleRepo/ElasticInquiryRepository.java | 7 + .../server/global/config/ElasticConfig.java | 28 +++ .../global/util/date/DateFormatUtil.java | 11 + src/main/resources/application-dev.yml | 4 +- src/main/resources/application-test.yml | 9 + .../admin/repository/ElasticSearchTest.java | 208 ++++++++++++++++++ .../support/IntegrationTestSupport.java | 12 + 19 files changed, 828 insertions(+), 13 deletions(-) create mode 100644 src/main/java/org/myteam/server/admin/document/ContentDocument.java create mode 100644 src/main/java/org/myteam/server/admin/document/ImprovementDocument.java create mode 100644 src/main/java/org/myteam/server/admin/document/InquiryDocument.java create mode 100644 src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java create mode 100644 src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticImproverRepository.java create mode 100644 src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticInquiryRepository.java create mode 100644 src/main/java/org/myteam/server/global/config/ElasticConfig.java create mode 100644 src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java diff --git a/build.gradle b/build.gradle index a65a59e5..ecaf6ff8 100644 --- a/build.gradle +++ b/build.gradle @@ -116,6 +116,12 @@ dependencies { implementation("com.blazebit:blaze-persistence-integration-querydsl-expressions-jakarta:1.6.15") implementation("com.blazebit:blaze-persistence-integration-hibernate-6.2:1.6.15") implementation("com.blazebit:blaze-persistence-core-impl-jakarta:1.6.15") + + + //elastic search 지원용 + implementation "org.springframework.data:spring-data-elasticsearch:5.5.3" + implementation 'co.elastic.clients:elasticsearch-java:8.18.5' + } test { diff --git a/src/main/java/org/myteam/server/admin/document/ContentDocument.java b/src/main/java/org/myteam/server/admin/document/ContentDocument.java new file mode 100644 index 00000000..55b8af1a --- /dev/null +++ b/src/main/java/org/myteam/server/admin/document/ContentDocument.java @@ -0,0 +1,68 @@ +package org.myteam.server.admin.document; + + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.admin.utill.enums.AdminControlType; +import org.myteam.server.admin.utill.enums.StaticDataType; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.*; + +import java.time.LocalDateTime; +import java.util.Date; +import java.util.UUID; + +@Getter +@NoArgsConstructor +@Setting(replicas = 0) +@Document(indexName = "contentdocument") +public class ContentDocument { + @Id + private String id; + + @Field(type=FieldType.Keyword,index = false) + private String email; + + @Field(type=FieldType.Text) + private String nickName; + + @Field(type=FieldType.Keyword) + private StaticDataType staticDataType; + + @Field(type=FieldType.Keyword) + private AdminControlType adminControlType; + + @Field(type=FieldType.Long,index = false) + private Long reportCount; + + @Field(type=FieldType.Long,index = false) + private Long contentId; + + @Field(type = FieldType.Text) + private String title; + + @Field(type = FieldType.Text) + private String content; + + @Field(type=FieldType.Date,format= DateFormat.date_hour_minute_second,index = false) + private LocalDateTime createDate; + + + @Builder + + public ContentDocument(String email, String nickName, StaticDataType staticDataType, AdminControlType adminControlType, + Long reportCount, Long contentId, String title, String content, LocalDateTime createDate) { + + this.email = email; + this.nickName = nickName; + this.staticDataType = staticDataType; + this.adminControlType = adminControlType; + this.reportCount = reportCount; + this.contentId = contentId; + this.title = title; + this.content = content; + this.createDate = createDate; + } +} diff --git a/src/main/java/org/myteam/server/admin/document/ImprovementDocument.java b/src/main/java/org/myteam/server/admin/document/ImprovementDocument.java new file mode 100644 index 00000000..be36f608 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/document/ImprovementDocument.java @@ -0,0 +1,64 @@ +package org.myteam.server.admin.document; + +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.improvement.domain.ImportantStatus; +import org.myteam.server.improvement.domain.ImprovementCount; +import org.myteam.server.improvement.domain.ImprovementStatus; +import org.myteam.server.member.entity.Member; +import org.springframework.data.elasticsearch.annotations.*; + +import java.time.LocalDateTime; +import java.util.UUID; + +import static org.myteam.server.improvement.domain.ImprovementStatus.PENDING; + +@Getter +@NoArgsConstructor +@Setting(replicas = 0) +@Document(indexName = "improvedocument") +public class ImprovementDocument { + + + @Id + @Field(type = FieldType.Long,index = false) + public Long id; + + @Field(type = FieldType.Keyword,index = false) + private UUID memberId; + + @Field(type = FieldType.Text) + private String title; + + @Field(type = FieldType.Text) + private String content; + + @Field(type = FieldType.Text) + private String nickName; + + @Field(type = FieldType.Keyword) + private ImprovementStatus improvementStatus; + + @Field(type = FieldType.Keyword) + private ImportantStatus importantStatus; + + @Field(type=FieldType.Date,format= DateFormat.date_hour_minute_second) + private LocalDateTime createDate; + + + @Builder + public ImprovementDocument(Long id, UUID memberId, String title, String content, String nickName, + ImprovementStatus improvementStatus, ImportantStatus importantStatus, + LocalDateTime createDate) { + this.id = id; + this.memberId = memberId; + this.title = title; + this.content = content; + this.nickName = nickName; + this.improvementStatus = improvementStatus; + this.importantStatus = importantStatus; + this.createDate = createDate; + } +} diff --git a/src/main/java/org/myteam/server/admin/document/InquiryDocument.java b/src/main/java/org/myteam/server/admin/document/InquiryDocument.java new file mode 100644 index 00000000..8ab07a13 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/document/InquiryDocument.java @@ -0,0 +1,55 @@ +package org.myteam.server.admin.document; + +import com.esotericsoftware.kryo.serializers.FieldSerializer; +import jakarta.persistence.*; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.inquiry.domain.InquiryCount; +import org.myteam.server.member.entity.Member; +import org.springframework.data.elasticsearch.annotations.*; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Getter +@NoArgsConstructor +@Setting(replicas = 0) +@Document(indexName = "inquirydocument") +public class InquiryDocument { + + @Id + @Field(type = FieldType.Long,index = false) + private Long id; + + @Field(type= FieldType.Text) + private String content; + + @Field(type=FieldType.Text) + private String nickName; + + @Field(type=FieldType.Date,format= DateFormat.date_hour_minute_second) + private LocalDateTime createDate; + + @Field(type=FieldType.Text) + private String email; + + @Field(type=FieldType.Boolean) + private Boolean isAdminAnswered; + + @Field(type=FieldType.Boolean) + private Boolean isMember; + + @Builder + public InquiryDocument(Long id, String content, String nickName, + LocalDateTime createDate, String email, Boolean isAdminAnswered, Boolean isMember) { + this.id = id; + this.content = content; + this.nickName = nickName; + this.createDate = createDate; + this.email = email; + this.isAdminAnswered = isAdminAnswered; + this.isMember = isMember; + } +} diff --git a/src/main/java/org/myteam/server/admin/dto/request/ContentRequestDto.java b/src/main/java/org/myteam/server/admin/dto/request/ContentRequestDto.java index 280f8e8f..00dfb958 100644 --- a/src/main/java/org/myteam/server/admin/dto/request/ContentRequestDto.java +++ b/src/main/java/org/myteam/server/admin/dto/request/ContentRequestDto.java @@ -5,13 +5,16 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.type.descriptor.DateTimeUtils; import org.myteam.server.admin.utill.enums.AdminControlType; import org.myteam.server.admin.utill.enums.StaticDataType; import org.myteam.server.board.domain.BoardSearchType; import org.myteam.server.global.util.date.DateFormatUtil; +import org.springframework.data.elasticsearch.annotations.DateFormat; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; public record ContentRequestDto() { @Getter @@ -56,6 +59,7 @@ public LocalDateTime provideStartTime() { if (this.startTime == null) { return null; } + LocalDate localDate = LocalDate.parse(startTime, DateFormatUtil.formatByDot); return localDate.atStartOfDay(); } @@ -64,6 +68,7 @@ public LocalDateTime provideEndTime() { if (this.endTime == null) { return null; } + LocalDate localDate = LocalDate.parse(endTime, DateFormatUtil.formatByDot); return localDate.atStartOfDay(); } diff --git a/src/main/java/org/myteam/server/admin/dto/request/ImproveRequestDto.java b/src/main/java/org/myteam/server/admin/dto/request/ImproveRequestDto.java index 6ed88a40..53cfecde 100644 --- a/src/main/java/org/myteam/server/admin/dto/request/ImproveRequestDto.java +++ b/src/main/java/org/myteam/server/admin/dto/request/ImproveRequestDto.java @@ -26,7 +26,6 @@ public final static class RequestImprovementList { private String title; private String content; private String nickName; - private String email; @Schema(example = "2025.06.06") private String startTime; @Schema(example = "2025.06.06") @@ -39,7 +38,7 @@ public final static class RequestImprovementList { @Builder public RequestImprovementList(ImprovementStatus improvementStatus, String title, String content, String nickName, - String startTime, String endTime, String email, int offset + String startTime, String endTime,int offset , ImportantStatus importantStatus) { this.improvementStatus = improvementStatus; this.title = title; @@ -47,7 +46,6 @@ public RequestImprovementList(ImprovementStatus improvementStatus, this.nickName = nickName; this.startTime = startTime; this.endTime = endTime; - this.email = email; this.offset = offset; this.importantStatus = importantStatus; } diff --git a/src/main/java/org/myteam/server/admin/dto/response/ResponseContentDto.java b/src/main/java/org/myteam/server/admin/dto/response/ResponseContentDto.java index 362738fb..e2470f4a 100644 --- a/src/main/java/org/myteam/server/admin/dto/response/ResponseContentDto.java +++ b/src/main/java/org/myteam/server/admin/dto/response/ResponseContentDto.java @@ -37,7 +37,6 @@ public ResponseContentSearch(Long contentId, String nickName, String staticDataT this.reportCount = reportCount; this.reported = reported; } - public void updateCountReported(Long count, String reported) { this.reported = reported; this.reportCount = count; diff --git a/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java b/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java index 24ca9931..b15d0140 100644 --- a/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java +++ b/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java @@ -1,27 +1,42 @@ package org.myteam.server.admin.repository; +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.*; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.ImprovementDocument; +import org.myteam.server.admin.document.InquiryDocument; +import org.myteam.server.admin.dto.request.InquiryRequestDto; +import org.myteam.server.admin.dto.response.InquiryResponseDto; import org.myteam.server.admin.utill.CreateAdminMemo; import org.myteam.server.admin.utill.enums.DateFormatEnum; import org.myteam.server.admin.utill.enums.StaticDataType; import org.myteam.server.global.util.date.DateFormatUtil; import org.myteam.server.improvement.domain.ImportantStatus; import org.myteam.server.improvement.domain.ImprovementStatus; +import org.myteam.server.improvement.dto.response.ImprovementResponse; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.client.elc.NativeQuery; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.UUID; +import java.util.stream.Collectors; import static org.myteam.server.admin.dto.request.AdminMemoRequestDto.AdminMemoImprovementRequest; import static org.myteam.server.admin.dto.response.ImprovementResponseDto.*; @@ -38,6 +53,7 @@ public class AdminImprovementSearchRepo { private final JPAQueryFactory queryFactory; private final CreateAdminMemo createAdminMemo; + private final ElasticsearchOperations elasticsearchOperations; public void createAdminMemo(AdminMemoImprovementRequest adminMemoRequest) { createAdminMemo.createImprovementMemo(adminMemoRequest, queryFactory); @@ -79,7 +95,6 @@ public Page getImprovementList(RequestImprovementList reque , contentSearchCond(requestImprovementList.getContent()), titleSearchCond(requestImprovementList.getTitle()), processStatusCond(requestImprovementList.getImprovementStatus()), - searchByEmail(requestImprovementList.getEmail()), searchByImportantStatus(requestImprovementList.getImportantStatus())) .orderBy(improvement.createDate.desc()) .offset(pageable.getOffset()) @@ -97,12 +112,47 @@ public Page getImprovementList(RequestImprovementList reque , contentSearchCond(requestImprovementList.getContent()), titleSearchCond(requestImprovementList.getTitle()), processStatusCond(requestImprovementList.getImprovementStatus()), - searchByEmail(requestImprovementList.getEmail()), searchByImportantStatus(requestImprovementList.getImportantStatus())) .fetchOne()).orElse(0L); return new PageImpl<>(responseImprovementList, pageable, count); } + + public List getImprovementByElasticSearch(RequestImprovementList requestImprovementList){ + List must=makeMustQuery(requestImprovementList); + List filter=filterQuery(requestImprovementList); + PageRequest pageRequest=PageRequest.of(requestImprovementList.getOffset(),10); + + Query query=new BoolQuery.Builder() + .filter(filter) + .must(must) + .build() + ._toQuery(); + + NativeQuery nativeQuery=NativeQuery.builder() + .withQuery(query) + .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") + .order(SortOrder.Desc))))) + .withPageable(pageRequest) + .build(); + SearchHits data=elasticsearchOperations.search(nativeQuery, ImprovementDocument.class); + + List improvements=data.stream().map(x->{ + ImprovementDocument doc=x.getContent(); + String importantStatus= doc.getImportantStatus().equals(ImportantStatus.LOW) ? "낮음" + :doc.getImportantStatus().equals(ImportantStatus.HIGH) ? "높음 ":"중간"; + String improveStatus=doc.getImprovementStatus().equals(ImprovementStatus.PENDING) ?"접수전" + :doc.getImprovementStatus().equals(ImprovementStatus.RECEIVED) ? "접수완료": "개선완료"; + return new ResponseImprovement( + doc.getId(), doc.getMemberId(),importantStatus,improveStatus,0 + ,doc.getNickName(),doc.getTitle(), + doc.getContent(),doc.getCreateDate().toString() + ); + }).collect(Collectors.toList()); + DateFormatUtil.makeElasticTimeByFormatter(improvements,DateFormatEnum.formatByDotReq); + return improvements; + } + public ResponseImprovementDetail getImprovementDetail(Long contentId) { ResponseImprovementDetail responseImprovementDetail = queryFactory .select( @@ -269,6 +319,52 @@ private Predicate searchByTimeLine(LocalDateTime startTime, LocalDateTime endTim return null; } return improvement.createDate.between(startTime, endTime); + } + + private List filterQuery(RequestImprovementList requestImprovementList){ + List filter=new ArrayList<>(); + if(requestImprovementList.getImportantStatus()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("importantStatus") + .value(requestImprovementList.getImportantStatus().name())); + filter.add(termQuery._toQuery()); + } + if(requestImprovementList.getImprovementStatus()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("improvementStatus") + .value(requestImprovementList.getImprovementStatus().name())); + filter.add(termQuery._toQuery()); + } + if(requestImprovementList.provideEndTime()!=null&&requestImprovementList.provideStartTime()!=null){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + RangeQuery rangeQuery=RangeQuery.of(r->r.date( + v->v.field("createDate") + .gte(requestImprovementList.provideStartTime().format(formatter)) + .lt(requestImprovementList.provideEndTime().format(formatter)) + )); + filter.add(rangeQuery._toQuery()); + } + return filter; + } + + public List makeMustQuery(RequestImprovementList requestImprovementList){ + List mustQuery=new ArrayList<>(); + + if(requestImprovementList.getContent()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("content") + .query(requestImprovementList.getContent())); + mustQuery.add(matchQuery._toQuery()); + } + if(requestImprovementList.getTitle()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("title") + .query(requestImprovementList.getTitle())); + mustQuery.add(matchQuery._toQuery()); + } + if(requestImprovementList.getNickName()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") + .query(requestImprovementList.getNickName()) + .fuzziness("AUTO")); + mustQuery.add(matchQuery._toQuery()); + } + return mustQuery; } } diff --git a/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java b/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java index 67fdad47..cc7ef8db 100644 --- a/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java +++ b/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java @@ -1,5 +1,8 @@ package org.myteam.server.admin.repository; +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.*; import com.blazebit.persistence.querydsl.BlazeJPAQuery; import com.blazebit.persistence.querydsl.BlazeJPAQueryFactory; import com.querydsl.core.types.Predicate; @@ -9,10 +12,15 @@ import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.hibernate.type.descriptor.DateTimeUtils; +import org.myteam.server.admin.document.ContentDocument; import org.myteam.server.admin.dto.ctes.QContentIdCte; import org.myteam.server.admin.dto.ctes.QContentTotInfoCte; import org.myteam.server.admin.dto.ctes.QSimpleReportCte; import org.myteam.server.admin.dto.response.CommonResponseDto; +import org.myteam.server.admin.dto.response.ResponseContentDto; +import org.myteam.server.admin.service.ContentSearchService; import org.myteam.server.admin.utill.enums.AdminControlType; import org.myteam.server.admin.utill.CreateAdminMemo; import org.myteam.server.admin.utill.enums.DateFormatEnum; @@ -21,15 +29,23 @@ import org.myteam.server.chat.block.domain.BanReason; import org.myteam.server.global.util.date.DateFormatUtil; import org.myteam.server.member.domain.MemberStatus; +import org.myteam.server.member.entity.Member; +import org.myteam.server.member.service.MemberReadService; import org.myteam.server.report.domain.ReportType; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.client.elc.NativeQuery; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.security.core.parameters.P; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; @@ -48,11 +64,14 @@ @Transactional @RequiredArgsConstructor @Repository +@Slf4j public class ContentSearchRepository { private final JPAQueryFactory queryFactory; private final BlazeJPAQueryFactory blazeJPAQueryFactory; private final CreateAdminMemo createAdminMemo; + private final ElasticsearchOperations elasticsearchOperations; + private final MemberReadService memberReadService; public void addAdminMemo(AdminMemoContentRequest adminMemoContentRequest) { @@ -232,6 +251,30 @@ public Page getDataList(RequestContentData adminContentRe return getAdminBoardList(adminContentResearch); } + public List useElasticSearchForUnionQuery(RequestContentData requestContentData){ + List mustQuery=makeMustQuery(requestContentData); + List filterQuery=makeFilterQuery(requestContentData); + PageRequest pageRequest=PageRequest.of(requestContentData.getOffset(),10); + Query query=new BoolQuery.Builder() + .filter(filterQuery) + .must(mustQuery) + .build() + ._toQuery(); + NativeQuery nativeQuery=NativeQuery.builder() + .withQuery(query) + .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") + .order(SortOrder.Desc))))) + .withPageable(pageRequest) + .build(); + SearchHits datas= elasticsearchOperations.search(nativeQuery, ContentDocument.class); + List responseContentSearches=datas.stream().map(x->{ + return mappingDocToDto(x.getContent()); + }).collect(Collectors.toList()); + + DateFormatUtil.makeElasticTimeByFormatter(responseContentSearches,DateFormatEnum.formatByDotReq); + return responseContentSearches; + } + public Page getWhenDataTypeIsNullWithUnion(RequestContentData adminContentResearch) { BoardSearchType boardSearchType = adminContentResearch.getBoardSearchType(); @@ -573,30 +616,30 @@ private Predicate searchByTimeLine(LocalDateTime startTime, LocalDateTime endTim } if (startTime != null & endTime == null) { - return board.createDate.after(startTime); + return board.createDate.goe(startTime); } if (startTime == null) { - return board.createDate.before(endTime); + return board.createDate.lt(endTime); } - return board.createDate.between(startTime, endTime); + return board.createDate.goe(startTime).and(board.createDate.lt(endTime)); } if (startTime != null & endTime == null) { - return comment1.createDate.after(startTime); + return comment1.createDate.goe(startTime); } if (endTime != null & startTime == null) { - return comment1.createDate.before(endTime); + return comment1.createDate.lt(endTime); } if (startTime == null & endTime == null) { return null; } - return comment1.createDate.between(startTime, endTime); + return comment1.createDate.goe(startTime).and(comment1.createDate.lt(endTime)); } @@ -721,4 +764,95 @@ private ResponseDetail editDataTimeAndAdminMemo(StaticDataType staticDataType, R return responseDetail; } + public List makeFilterQuery(RequestContentData requestContentData){ + List filterQuery=new ArrayList<>(); + if(requestContentData.getAdminControlType()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("adminControlType") + .value(requestContentData.getAdminControlType().name())); + filterQuery.add(termQuery._toQuery()); + } + if(requestContentData.provideEndTime()!=null && requestContentData.provideEndTime()!=null){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + RangeQuery rangeQuery=new RangeQuery.Builder() + .date(v->v.field("createDate") + .gte(requestContentData.provideStartTime().format(formatter)) + .lte(requestContentData.provideEndTime().format(formatter))) + .build(); + filterQuery.add(rangeQuery._toQuery()); + } + if(requestContentData.getIsReported()!=null){ + if(requestContentData.getIsReported()) { + RangeQuery rangeQuery = new RangeQuery.Builder() + .number(v -> v.field("reportCount") + .gt(Double.valueOf("0"))) + .build(); + filterQuery.add(rangeQuery._toQuery()); + } + else{ + RangeQuery rangeQuery = new RangeQuery.Builder() + .number(v -> v.field("reportCount") + .lte(Double.valueOf("0"))) + .build(); + filterQuery.add(rangeQuery._toQuery()); + } + } + if(requestContentData.getStaticDataType()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("staticDataType") + .value(requestContentData.getStaticDataType().name())); + filterQuery.add(termQuery._toQuery()); + } + + return filterQuery; + } + public List makeMustQuery(RequestContentData requestContentData){ + List mustQuery=new ArrayList<>(); + BoardSearchType boardSearchType=requestContentData.getBoardSearchType(); + String searchKeyWord=requestContentData.getSearchKeyWord(); + if(boardSearchType!=null){ + if(boardSearchType==BoardSearchType.CONTENT||boardSearchType==BoardSearchType.COMMENT){ + MatchQuery matchQuery=MatchQuery.of(m-> + m.field("content") + .query(searchKeyWord)); + mustQuery.add(matchQuery._toQuery()); + } + if(boardSearchType==BoardSearchType.TITLE_CONTENT){ + MultiMatchQuery multiMatchQuery=MultiMatchQuery.of( + m->m.fields(List.of("content","title")) + .query(searchKeyWord) + ); + mustQuery.add(multiMatchQuery._toQuery()); + } + if(boardSearchType==BoardSearchType.TITLE){ + MatchQuery matchQuery=MatchQuery.of(m-> + m.field("title") + .query(searchKeyWord)); + mustQuery.add(matchQuery._toQuery()); + } + if(requestContentData.getBoardSearchType().equals(BoardSearchType.NICKNAME)){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") + .query(requestContentData.getSearchKeyWord()) + .fuzziness("AUTO")); + mustQuery.add(matchQuery._toQuery()); + } + } + return mustQuery; + } + + public ResponseContentSearch mappingDocToDto(ContentDocument contentDocument){ + Member member1=memberReadService.findByEmail(contentDocument.getEmail()); + String status=member1.getStatus().equals(MemberStatus.ACTIVE) ? "정상" : + member1.getStatus().equals(MemberStatus.WARNED) ? "경고" : + member1.getStatus().equals(MemberStatus.PENDING) ? "대기중":"정지"; + String reported=contentDocument.getReportCount()>0 ? "신고" :"미신고"; + String staticDataType=contentDocument.getStaticDataType().equals(StaticDataType.BOARD) ? "게시글": + contentDocument.getStaticDataType().equals(StaticDataType.COMMENT) ? "댓글" + : "채팅"; + ResponseContentSearch responseContentSearch=new ResponseContentSearch( + contentDocument.getContentId(),member1.getNickname(),staticDataType, + contentDocument.getContent(),contentDocument.getCreateDate().toString(),status, + contentDocument.getAdminControlType().name(),contentDocument.getReportCount(),reported + ); + return responseContentSearch; + } + } diff --git a/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java b/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java index 4753a46e..76c1044f 100644 --- a/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java +++ b/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java @@ -1,25 +1,38 @@ package org.myteam.server.admin.repository; +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.*; import com.querydsl.core.types.Predicate; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.CaseBuilder; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.document.InquiryDocument; import org.myteam.server.admin.entity.AdminContentMemo; import org.myteam.server.admin.utill.CreateAdminMemo; import org.myteam.server.admin.utill.enums.DateFormatEnum; import org.myteam.server.admin.utill.enums.StaticDataType; import org.myteam.server.global.util.date.DateFormatUtil; +import org.myteam.server.match.match.domain.Match; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; +import org.springframework.data.elasticsearch.client.elc.NativeQuery; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; + import static org.myteam.server.admin.dto.request.AdminMemoRequestDto.AdminMemoInquiryRequest; import static org.myteam.server.admin.dto.response.InquiryResponseDto.*; import static org.myteam.server.admin.dto.response.InquiryResponseDto.ResponseInquiryList; @@ -35,6 +48,7 @@ public class InquirySearchRepo { private final JPAQueryFactory queryFactory; private final CreateAdminMemo createAdminMemo; + private final ElasticsearchOperations elasticsearchOperations; public AdminContentMemo createAdminMemo(AdminMemoInquiryRequest adminMemoRequest) { @@ -178,6 +192,43 @@ public Page getInquiryListByCond(RequestInquiryListCond return new PageImpl<>(responseInquiryListConds, pageable, count); } + public List getInquiryListByContElasticSearch(RequestInquiryListCond requestInquiryListCond){ + List filter=makeFilterQuery(requestInquiryListCond); + List must=makeMustQuery(requestInquiryListCond); + PageRequest pageRequest=PageRequest.of(requestInquiryListCond.getOffset(),10); + + Query query=new BoolQuery.Builder() + .filter(filter) + .must(must) + .build() + ._toQuery(); + + NativeQuery nativeQuery=NativeQuery.builder() + .withQuery(query) + .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") + .order(SortOrder.Desc))))) + .withPageable(pageRequest) + .build(); + SearchHits data=elasticsearchOperations.search(nativeQuery, InquiryDocument.class); + + List responseInquiryListConds=data.stream().map(x->{ + InquiryDocument doc=x.getContent(); + String isAnswered= doc.getIsAdminAnswered() ? "답변완료" :"답변대기"; + String isMember=doc.getIsMember() ? "회원":"비회원"; + String nicknameEmail=doc.getNickName()==null ? doc.getEmail() : doc.getNickName(); + + return new ResponseInquiryListCond( + doc.getId(),isAnswered,isMember,nicknameEmail,doc.getContent(),doc.getEmail(), + doc.getCreateDate().toString() + ); + }).collect(Collectors.toList()); + + DateFormatUtil.makeElasticTimeByFormatter(responseInquiryListConds,DateFormatEnum.formatByDotReq); + + return responseInquiryListConds; + + } + private Predicate memberOrNot(Boolean isMember) { if (isMember == null) { @@ -239,5 +290,53 @@ private Predicate searchByTimeLine(LocalDateTime startTime, LocalDateTime endTim } + private List makeFilterQuery(RequestInquiryListCond requestInquiryListCond){ + List filterQuery=new ArrayList<>(); + if(requestInquiryListCond.getIsMember()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("isMember") + .value(requestInquiryListCond.getIsMember())); + filterQuery.add(termQuery._toQuery()); + } + if(requestInquiryListCond.getIsAnswered()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("isAdminAnswered") + .value(requestInquiryListCond.getIsAnswered())); + filterQuery.add(termQuery._toQuery()); + } + if(requestInquiryListCond.provideStartTime()!=null&&requestInquiryListCond.provideEndTime()!=null){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + RangeQuery rangeQuery=RangeQuery.of(r->r.date( + v->v.field("createDate") + .gte(requestInquiryListCond.provideStartTime().format(formatter)) + .lt(requestInquiryListCond.provideEndTime().format(formatter)) + )); + filterQuery.add(rangeQuery._toQuery()); + } + if(requestInquiryListCond.getEmail()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("email") + .query(requestInquiryListCond.getEmail()) + .fuzziness("AUTO")); + filterQuery.add(matchQuery._toQuery()); + } + + return filterQuery; + } + public List makeMustQuery(RequestInquiryListCond requestInquiryListCond){ + List mustQuery=new ArrayList<>(); + + if(requestInquiryListCond.getContent()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("content") + .query(requestInquiryListCond.getContent())); + mustQuery.add(matchQuery._toQuery()); + } + + if(requestInquiryListCond.getNickName()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") + .query(requestInquiryListCond.getNickName()) + .fuzziness("AUTO")); + mustQuery.add(matchQuery._toQuery()); + } + return mustQuery; + } + } diff --git a/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java new file mode 100644 index 00000000..40a22fa4 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java @@ -0,0 +1,7 @@ +package org.myteam.server.admin.repository.simpleRepo; + +import org.myteam.server.admin.document.ContentDocument; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +public interface ElasticContentRepository extends ElasticsearchRepository { +} diff --git a/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticImproverRepository.java b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticImproverRepository.java new file mode 100644 index 00000000..dfcf5e9e --- /dev/null +++ b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticImproverRepository.java @@ -0,0 +1,7 @@ +package org.myteam.server.admin.repository.simpleRepo; + +import org.myteam.server.admin.document.ImprovementDocument; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +public interface ElasticImproverRepository extends ElasticsearchRepository { +} diff --git a/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticInquiryRepository.java b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticInquiryRepository.java new file mode 100644 index 00000000..01baefb8 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticInquiryRepository.java @@ -0,0 +1,7 @@ +package org.myteam.server.admin.repository.simpleRepo; + +import org.myteam.server.admin.document.InquiryDocument; +import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; + +public interface ElasticInquiryRepository extends ElasticsearchRepository { +} diff --git a/src/main/java/org/myteam/server/global/config/ElasticConfig.java b/src/main/java/org/myteam/server/global/config/ElasticConfig.java new file mode 100644 index 00000000..c528605c --- /dev/null +++ b/src/main/java/org/myteam/server/global/config/ElasticConfig.java @@ -0,0 +1,28 @@ +package org.myteam.server.global.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.elasticsearch.client.ClientConfiguration; +import org.springframework.data.elasticsearch.client.elc.ElasticsearchConfiguration; + + +@Configuration +public class ElasticConfig extends ElasticsearchConfiguration { + + @Value("${spring.elasticsearch.username}") + private String username; + + @Value("${spring.elasticsearch.password}") + private String password; + + @Value("${spring.elasticsearch.uris}") + private String[] esHost; + + @Override + public ClientConfiguration clientConfiguration() { + return ClientConfiguration.builder() + .connectedTo(esHost) + .withBasicAuth(username,password) + .build(); + } +} diff --git a/src/main/java/org/myteam/server/global/util/date/DateFormatUtil.java b/src/main/java/org/myteam/server/global/util/date/DateFormatUtil.java index 9f2b4eb8..0e1c1ba4 100644 --- a/src/main/java/org/myteam/server/global/util/date/DateFormatUtil.java +++ b/src/main/java/org/myteam/server/global/util/date/DateFormatUtil.java @@ -45,5 +45,16 @@ public static void makeTimeByFormatter(List data, , DateFormatUtil.FLEXIBLE_NANO_FORMATTER))); }); } + public static void makeElasticTimeByFormatter(List data, DateFormatEnum dateFormatEnum){ + data.stream() + .forEach(x -> { + x.updateCreateDate( + dateFormatEnum.equals(DateFormatEnum.formatByDotReq) ? + DateFormatUtil.formatByDot + .format(LocalDateTime.parse(x.getCreateDate())) + : DateFormatUtil.formatByDotAndSlash + .format(LocalDateTime.parse(x.getCreateDate()))); + }); + } } diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 02f8e56f..67bb2ba0 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -1,7 +1,6 @@ spring: jackson: time-zone: Asia/Seoul - datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://${DB_ENDPOINT}:3306/${DB_NAME}?useSSL=false&serverTimezone=Asia/Seoul @@ -31,6 +30,9 @@ spring: host: ${REDIS_HOST} password: ${REDIS_PASSWORD} port: ${REDIS_PORT} + elasticsearch: + repositories: + enabled: true logging: level: diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 1e614a0b..1cb84464 100755 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -1,4 +1,9 @@ spring: + elasticsearch: + username: elastic + password: NH9OIw*T7rCotS8vrpsj #로컬환경실행시에 랜덤으로 배정되는 비밀번혼대 사용자마다 다르니까 알아서 바꿔야될거같습니다. + uris: + localhost:9200 datasource: url: jdbc:h2:mem:~/playhive;MODE=MySQL;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE driver-class-name: org.h2.Driver @@ -136,3 +141,7 @@ google: name: googleApi url: https://www.googleapis.com apiKey: test +logging: + level.org: + springframework.data.elasticsearch: DEBUG + #elasticsearch.client: DEBUG \ No newline at end of file diff --git a/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java b/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java new file mode 100644 index 00000000..fd95fbf7 --- /dev/null +++ b/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java @@ -0,0 +1,208 @@ +package org.myteam.server.admin.repository; + + +import co.elastic.clients.json.JsonpUtils; +import com.querydsl.jpa.impl.JPAQueryFactory; +import io.lettuce.core.ScriptOutputType; +import org.assertj.core.api.Assertions; +import org.junit.Before; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.document.ImprovementDocument; +import org.myteam.server.admin.document.InquiryDocument; +import org.myteam.server.admin.dto.request.ContentRequestDto; +import org.myteam.server.admin.dto.request.ImproveRequestDto; +import org.myteam.server.admin.dto.request.InquiryRequestDto; +import org.myteam.server.admin.dto.response.ImprovementResponseDto; +import org.myteam.server.admin.dto.response.InquiryResponseDto; +import org.myteam.server.admin.dto.response.ResponseContentDto; +import org.myteam.server.admin.repository.simpleRepo.ElasticContentRepository; +import org.myteam.server.admin.repository.simpleRepo.ElasticImproverRepository; +import org.myteam.server.admin.repository.simpleRepo.ElasticInquiryRepository; +import org.myteam.server.admin.utill.enums.AdminControlType; +import org.myteam.server.admin.utill.enums.StaticDataType; +import org.myteam.server.board.domain.Board; +import org.myteam.server.board.domain.BoardSearchType; +import org.myteam.server.board.domain.CategoryType; +import org.myteam.server.global.domain.Category; +import org.myteam.server.global.util.date.DateFormatUtil; +import org.myteam.server.improvement.domain.ImportantStatus; +import org.myteam.server.improvement.domain.Improvement; +import org.myteam.server.improvement.domain.ImprovementStatus; +import org.myteam.server.improvement.repository.ImprovementQueryRepository; +import org.myteam.server.inquiry.domain.Inquiry; +import org.myteam.server.member.entity.Member; +import org.myteam.server.support.IntegrationTestSupport; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.data.domain.Page; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; +import java.util.List; + +import static org.myteam.server.admin.dto.request.ContentRequestDto.*; +import static org.myteam.server.admin.dto.response.ResponseContentDto.*; +import static org.myteam.server.board.domain.QBoard.board; + +@SpringBootTest +public class ElasticSearchTest extends IntegrationTestSupport { + static private DataSource testDataSource; + + @Autowired + ContentSearchRepository contentSearchRepository; + @Autowired + InquirySearchRepo inquirySearchRepo; + @Autowired + AdminImprovementSearchRepo adminImprovementSearchRepo; + + @Autowired + JPAQueryFactory queryFactory; + + Member m; + @BeforeAll + static void setupH2CustomFunctions(@Autowired DataSource dataSource) { + testDataSource = dataSource; // + try (Connection conn = testDataSource.getConnection(); + Statement stmt = conn.createStatement()) { + + stmt.execute("CREATE ALIAS IF NOT EXISTS DATE_FORMAT FOR 'org.myteam.server.admin.utill.StaticUtil.dateFormat'"); + System.out.println("H2에 DATE_FORMAT 함수 별칭이 성공적으로 등록되었습니다."); + } catch (SQLException e) { + System.err.println("H2 함수 별칭 등록 중 오류 발생: " + e.getMessage()); + e.printStackTrace(); + + throw new RuntimeException("Failed to register H2 DATE_FORMAT alias", e); + } + } + + + @BeforeEach + void setBeforeTest(){ + m=createMember(0); + + for(int i=0;10>i;i++){ + if(i%2==0){ + Board b=createBoard(m, Category.ESPORTS, CategoryType.FREE,"hello","오늘은 날씨가 매우 맑아서 공원에 나가 산책을 하기로 했다. 새들이 지저귀는 소리를 들으며 길을 걷다 보면 마음이 편안해진다. hello 친구들과 함께 커피를 마시며 이야기를 나누는 시간도 즐겁다. 점심으로는 간단하게 김밥과 떡볶이를 먹고," + + " 오후에는 책을 읽으며 휴식을 취했다. 저녁이 되자 노을이 아름답게 물들어 하루를 마무리했다."); + Inquiry inquiry=createInquiry(m); + Improvement improvement=createImprovement(m,false); + ContentDocument c + =ContentDocument + .builder() + .staticDataType(StaticDataType.BOARD) + .adminControlType(AdminControlType.HIDDEN) + .title("hello") + .contentId(b.getId()) + .content(b.getContent()) + .createDate(b.getCreateDate()) + .reportCount(0L) + .email(m.getEmail()) + .build(); + InquiryDocument inquiryDoc=InquiryDocument.builder() + .id(inquiry.getId()) + .content(inquiry.getContent()) + .isAdminAnswered(inquiry.isAdminAnswered()) + .isMember(true) + .createDate(inquiry.getCreatedAt()) + .email(inquiry.getEmail()) + .build(); + ImprovementDocument improvementDocument=ImprovementDocument.builder() + .id(improvement.getId()) + .improvementStatus(ImprovementStatus.PENDING) + .nickName(m.getNickname()) + .content(improvement.getContent()) + .title(improvement.getTitle()) + .importantStatus(ImportantStatus.NORMAL) + .createDate(improvement.getCreateDate()) + .title(improvement.getTitle()) + .build(); + elasticInquiryRepository.save(inquiryDoc); + elasticContentRepository.save(c); + elasticImproverRepository.save(improvementDocument); + } + else{ + Board b=createBoard(m, Category.ESPORTS, CategoryType.FREE,"hello", + "오늘은 날씨가 매우 맑아서 공원에 나가 산책을 하기로 했다. 새들이 지저귀는 소리를 들으며 길을 걷다 보면 마음이 편안해진다. 친구들과 함께 커피를 마시며 이야기를 나누는 시간도 즐겁다. " + + "점심으로는 간단하게 김밥과 떡볶이를 먹고, 오후에는 책을 읽으며 휴식을 취했다. 저녁이 되자 노을이 아름답게 물들어 하루를 마무리했다."); + ContentDocument c + =ContentDocument + .builder() + .staticDataType(StaticDataType.BOARD) + .adminControlType(AdminControlType.HIDDEN) + .title("hello") + .contentId(b.getId()) + .content(b.getContent()) + .createDate(b.getCreateDate()) + .reportCount(0L) + .email(m.getEmail()) + .build(); + elasticContentRepository.save(c); + } + } + + } + + @Test + void contentTest(){ + + LocalDateTime now=LocalDateTime.now(); + LocalDateTime end=now.plusDays(1L); + String startTime= DateFormatUtil.formatByDot.format(now); + String endTime=DateFormatUtil.formatByDot.format(end); + + ContentRequestDto.RequestContentData requestContentData= + RequestContentData + .builder() + .staticDataType(StaticDataType.BOARD) + .boardSearchType(BoardSearchType.CONTENT) + .searchKeyWord("hello") + .startTime(startTime) + .endTime(endTime) + .reported(false) + .offset(1) + .build(); + List responseContentSearches + =contentSearchRepository.useElasticSearchForUnionQuery(requestContentData); + Assertions.assertThat(responseContentSearches.size()).isEqualTo(5); + + + + ImproveRequestDto.RequestImprovementList requestImprovementList + = ImproveRequestDto.RequestImprovementList.builder() + .improvementStatus(ImprovementStatus.PENDING) + .importantStatus(ImportantStatus.NORMAL) + .endTime(endTime) + .nickName(m.getNickname()) + .startTime(startTime) + .offset(1) + .build(); + + List responseImprovements + =adminImprovementSearchRepo.getImprovementByElasticSearch(requestImprovementList); + + Assertions.assertThat(responseImprovements.size()).isEqualTo(5); + + InquiryRequestDto.RequestInquiryListCond requestInquiryListCond= + InquiryRequestDto.RequestInquiryListCond.builder() + .isMember(true) + .offset(1) + .startTime(startTime) + .endTime(endTime) + .email(m.getEmail()) + .build(); + + List responseInquiryLists + =inquirySearchRepo.getInquiryListByContElasticSearch(requestInquiryListCond); + Assertions.assertThat(responseInquiryLists.size()).isEqualTo(5); + + + } +} diff --git a/src/test/java/org/myteam/server/support/IntegrationTestSupport.java b/src/test/java/org/myteam/server/support/IntegrationTestSupport.java index afa3d42f..cd37e856 100644 --- a/src/test/java/org/myteam/server/support/IntegrationTestSupport.java +++ b/src/test/java/org/myteam/server/support/IntegrationTestSupport.java @@ -108,6 +108,15 @@ public abstract class IntegrationTestSupport extends TestDriverSupport { protected AdminInquiryChangeLogRepo adminInquiryChangeLogRepo; @Autowired protected AdminMemberMemoRepo adminMemberMemoRepo; + + @Autowired + protected ElasticInquiryRepository elasticInquiryRepository; + @Autowired + protected ElasticImproverRepository elasticImproverRepository; + + @Autowired + protected ElasticContentRepository elasticContentRepository; + @AfterEach void tearDown() { adminMemberMemoRepo.deleteAllInBatch();; @@ -139,6 +148,9 @@ void tearDown() { memberActivityRepository.deleteAllInBatch(); memberAccessRepository.deleteAllInBatch(); memberJpaRepository.deleteAllInBatch(); + elasticImproverRepository.deleteAll(); + elasticInquiryRepository.deleteAll(); + elasticContentRepository.deleteAll(); } @Transactional From 7bebda1e9dac0e86f392d97267ddc9b2ef3e8612 Mon Sep 17 00:00:00 2001 From: dong3058 Date: Thu, 4 Sep 2025 17:31:05 +0900 Subject: [PATCH 2/5] fix dev-yml --- src/main/resources/application-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 67bb2ba0..79f30c49 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -6,7 +6,7 @@ spring: url: jdbc:mysql://${DB_ENDPOINT}:3306/${DB_NAME}?useSSL=false&serverTimezone=Asia/Seoul username: playhive password: ${DB_PASSWORD} - + #elastic 삭제 jpa: show-sql: false properties: From 96dc0f0e8c739566d142fda94fec618779e05511 Mon Sep 17 00:00:00 2001 From: dong3058 Date: Thu, 4 Sep 2025 17:33:22 +0900 Subject: [PATCH 3/5] fix dev-yml --- src/main/resources/application-dev.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 79f30c49..986fcf15 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -6,7 +6,7 @@ spring: url: jdbc:mysql://${DB_ENDPOINT}:3306/${DB_NAME}?useSSL=false&serverTimezone=Asia/Seoul username: playhive password: ${DB_PASSWORD} - #elastic 삭제 + jpa: show-sql: false properties: @@ -30,9 +30,6 @@ spring: host: ${REDIS_HOST} password: ${REDIS_PASSWORD} port: ${REDIS_PORT} - elasticsearch: - repositories: - enabled: true logging: level: From 736089fdc01254bb03f8e711c5618e8ed90bf986 Mon Sep 17 00:00:00 2001 From: dong3058 Date: Thu, 4 Sep 2025 17:43:16 +0900 Subject: [PATCH 4/5] cancle test code --- .../myteam/server/admin/repository/ElasticSearchTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java b/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java index fd95fbf7..e3c1a9bd 100644 --- a/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java +++ b/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java @@ -67,7 +67,7 @@ public class ElasticSearchTest extends IntegrationTestSupport { JPAQueryFactory queryFactory; Member m; - @BeforeAll + //@BeforeAll static void setupH2CustomFunctions(@Autowired DataSource dataSource) { testDataSource = dataSource; // try (Connection conn = testDataSource.getConnection(); @@ -84,7 +84,7 @@ static void setupH2CustomFunctions(@Autowired DataSource dataSource) { } - @BeforeEach + //@BeforeEach void setBeforeTest(){ m=createMember(0); @@ -150,7 +150,7 @@ void setBeforeTest(){ } - @Test + //@Test void contentTest(){ LocalDateTime now=LocalDateTime.now(); From f36a7b6c765c75872e7ed8ea1e0274fa338741ff Mon Sep 17 00:00:00 2001 From: dong3058 Date: Mon, 8 Sep 2025 21:56:34 +0900 Subject: [PATCH 5/5] fix: return type chaged to page impl --- .../admin/document/ContentDocument.java | 15 +- .../AdminImprovementSearchRepo.java | 80 +------- .../repository/ContentElasticRepository.java | 172 ++++++++++++++++++ .../repository/ContentSearchRepository.java | 118 +----------- .../repository/ImproveElasticRepository.java | 118 ++++++++++++ .../repository/InquiryElasticRepository.java | 114 ++++++++++++ .../admin/repository/InquirySearchRepo.java | 83 --------- .../simpleRepo/ElasticContentRepository.java | 4 + .../elastic/ElasticSearchSaveHandler.java | 60 ++++++ .../elastic/event/ElasticContentEvent.java | 60 ++++++ .../event/ElasticContentUpdateEvent.java | 54 ++++++ .../elastic/event/ElasticImproveEvent.java | 55 ++++++ .../event/ElasticImproveUpdateEvent.java | 48 +++++ .../elastic/event/ElasticInquiryEvent.java | 45 +++++ .../event/ElasticInquiryUpdateEvent.java | 45 +++++ .../admin/repository/ElasticSearchTest.java | 34 ++-- 16 files changed, 806 insertions(+), 299 deletions(-) create mode 100644 src/main/java/org/myteam/server/admin/repository/ContentElasticRepository.java create mode 100644 src/main/java/org/myteam/server/admin/repository/ImproveElasticRepository.java create mode 100644 src/main/java/org/myteam/server/admin/repository/InquiryElasticRepository.java create mode 100644 src/main/java/org/myteam/server/global/elastic/ElasticSearchSaveHandler.java create mode 100644 src/main/java/org/myteam/server/global/elastic/event/ElasticContentEvent.java create mode 100644 src/main/java/org/myteam/server/global/elastic/event/ElasticContentUpdateEvent.java create mode 100644 src/main/java/org/myteam/server/global/elastic/event/ElasticImproveEvent.java create mode 100644 src/main/java/org/myteam/server/global/elastic/event/ElasticImproveUpdateEvent.java create mode 100644 src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryEvent.java create mode 100644 src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryUpdateEvent.java diff --git a/src/main/java/org/myteam/server/admin/document/ContentDocument.java b/src/main/java/org/myteam/server/admin/document/ContentDocument.java index 55b8af1a..a65825eb 100644 --- a/src/main/java/org/myteam/server/admin/document/ContentDocument.java +++ b/src/main/java/org/myteam/server/admin/document/ContentDocument.java @@ -34,8 +34,8 @@ public class ContentDocument { @Field(type=FieldType.Keyword) private AdminControlType adminControlType; - @Field(type=FieldType.Long,index = false) - private Long reportCount; + @Field(type=FieldType.Boolean) + private Boolean isReported; @Field(type=FieldType.Long,index = false) private Long contentId; @@ -51,18 +51,19 @@ public class ContentDocument { @Builder - - public ContentDocument(String email, String nickName, StaticDataType staticDataType, AdminControlType adminControlType, - Long reportCount, Long contentId, String title, String content, LocalDateTime createDate) { - + public ContentDocument(String id,String email, String nickName, StaticDataType staticDataType, AdminControlType adminControlType, + Boolean isReported, Long contentId, String title, String content, LocalDateTime createDate) { + this.id=id; this.email = email; this.nickName = nickName; this.staticDataType = staticDataType; this.adminControlType = adminControlType; - this.reportCount = reportCount; + this.isReported=isReported; this.contentId = contentId; this.title = title; this.content = content; this.createDate = createDate; } + + } diff --git a/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java b/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java index b15d0140..7cf5c6a4 100644 --- a/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java +++ b/src/main/java/org/myteam/server/admin/repository/AdminImprovementSearchRepo.java @@ -53,7 +53,6 @@ public class AdminImprovementSearchRepo { private final JPAQueryFactory queryFactory; private final CreateAdminMemo createAdminMemo; - private final ElasticsearchOperations elasticsearchOperations; public void createAdminMemo(AdminMemoImprovementRequest adminMemoRequest) { createAdminMemo.createImprovementMemo(adminMemoRequest, queryFactory); @@ -118,40 +117,7 @@ public Page getImprovementList(RequestImprovementList reque } - public List getImprovementByElasticSearch(RequestImprovementList requestImprovementList){ - List must=makeMustQuery(requestImprovementList); - List filter=filterQuery(requestImprovementList); - PageRequest pageRequest=PageRequest.of(requestImprovementList.getOffset(),10); - - Query query=new BoolQuery.Builder() - .filter(filter) - .must(must) - .build() - ._toQuery(); - - NativeQuery nativeQuery=NativeQuery.builder() - .withQuery(query) - .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") - .order(SortOrder.Desc))))) - .withPageable(pageRequest) - .build(); - SearchHits data=elasticsearchOperations.search(nativeQuery, ImprovementDocument.class); - - List improvements=data.stream().map(x->{ - ImprovementDocument doc=x.getContent(); - String importantStatus= doc.getImportantStatus().equals(ImportantStatus.LOW) ? "낮음" - :doc.getImportantStatus().equals(ImportantStatus.HIGH) ? "높음 ":"중간"; - String improveStatus=doc.getImprovementStatus().equals(ImprovementStatus.PENDING) ?"접수전" - :doc.getImprovementStatus().equals(ImprovementStatus.RECEIVED) ? "접수완료": "개선완료"; - return new ResponseImprovement( - doc.getId(), doc.getMemberId(),importantStatus,improveStatus,0 - ,doc.getNickName(),doc.getTitle(), - doc.getContent(),doc.getCreateDate().toString() - ); - }).collect(Collectors.toList()); - DateFormatUtil.makeElasticTimeByFormatter(improvements,DateFormatEnum.formatByDotReq); - return improvements; - } + public ResponseImprovementDetail getImprovementDetail(Long contentId) { ResponseImprovementDetail responseImprovementDetail = queryFactory @@ -321,50 +287,6 @@ private Predicate searchByTimeLine(LocalDateTime startTime, LocalDateTime endTim return improvement.createDate.between(startTime, endTime); } - private List filterQuery(RequestImprovementList requestImprovementList){ - List filter=new ArrayList<>(); - if(requestImprovementList.getImportantStatus()!=null){ - TermQuery termQuery=TermQuery.of(t->t.field("importantStatus") - .value(requestImprovementList.getImportantStatus().name())); - filter.add(termQuery._toQuery()); - } - if(requestImprovementList.getImprovementStatus()!=null){ - TermQuery termQuery=TermQuery.of(t->t.field("improvementStatus") - .value(requestImprovementList.getImprovementStatus().name())); - filter.add(termQuery._toQuery()); - } - if(requestImprovementList.provideEndTime()!=null&&requestImprovementList.provideStartTime()!=null){ - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); - RangeQuery rangeQuery=RangeQuery.of(r->r.date( - v->v.field("createDate") - .gte(requestImprovementList.provideStartTime().format(formatter)) - .lt(requestImprovementList.provideEndTime().format(formatter)) - )); - filter.add(rangeQuery._toQuery()); - } - return filter; - } - public List makeMustQuery(RequestImprovementList requestImprovementList){ - List mustQuery=new ArrayList<>(); - if(requestImprovementList.getContent()!=null){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("content") - .query(requestImprovementList.getContent())); - mustQuery.add(matchQuery._toQuery()); - } - if(requestImprovementList.getTitle()!=null){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("title") - .query(requestImprovementList.getTitle())); - mustQuery.add(matchQuery._toQuery()); - } - if(requestImprovementList.getNickName()!=null){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") - .query(requestImprovementList.getNickName()) - .fuzziness("AUTO")); - mustQuery.add(matchQuery._toQuery()); - } - - return mustQuery; - } } diff --git a/src/main/java/org/myteam/server/admin/repository/ContentElasticRepository.java b/src/main/java/org/myteam/server/admin/repository/ContentElasticRepository.java new file mode 100644 index 00000000..93836990 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/repository/ContentElasticRepository.java @@ -0,0 +1,172 @@ +package org.myteam.server.admin.repository; + +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.*; +import com.blazebit.persistence.querydsl.BlazeJPAQueryFactory; +import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.dto.request.ContentRequestDto; +import org.myteam.server.admin.dto.response.ResponseContentDto; +import org.myteam.server.admin.utill.enums.DateFormatEnum; +import org.myteam.server.admin.utill.enums.StaticDataType; +import org.myteam.server.board.domain.BoardSearchType; +import org.myteam.server.global.util.date.DateFormatUtil; +import org.myteam.server.member.domain.MemberStatus; +import org.myteam.server.member.entity.Member; +import org.myteam.server.member.service.MemberReadService; +import org.myteam.server.report.domain.ReportType; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.client.elc.NativeQuery; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.stereotype.Repository; + +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.myteam.server.admin.dto.response.ResponseContentDto.*; +import static org.myteam.server.report.domain.QReport.report; + +@RequiredArgsConstructor +@Repository +public class ContentElasticRepository { + + private final ElasticsearchOperations elasticsearchOperations; + private final MemberReadService memberReadService; + private final BlazeJPAQueryFactory blazeJPAQueryFactory; + + public Page useElasticSearchForUnionQuery(ContentRequestDto.RequestContentData requestContentData){ + List mustQuery=makeMustQuery(requestContentData); + List filterQuery=makeFilterQuery(requestContentData); + PageRequest pageRequest=PageRequest.of(requestContentData.getOffset(),10); + Query query=new BoolQuery.Builder() + .filter(filterQuery) + .must(mustQuery) + .build() + ._toQuery(); + NativeQuery nativeQuery=NativeQuery.builder() + .withQuery(query) + .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") + .order(SortOrder.Desc))))) + .withPageable(pageRequest) + .build(); + + + SearchHits datas= elasticsearchOperations.search(nativeQuery, ContentDocument.class); + List responseContentSearches=datas.stream().map(x->{ + return mappingDocToDto(x.getContent()); + }).collect(Collectors.toList()); + + DateFormatUtil.makeElasticTimeByFormatter(responseContentSearches, DateFormatEnum.formatByDotReq); + return new PageImpl<>(responseContentSearches,pageRequest,datas.getTotalHits()); + } + + + + private List makeFilterQuery(ContentRequestDto.RequestContentData requestContentData){ + List filterQuery=new ArrayList<>(); + if(requestContentData.getAdminControlType()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("adminControlType") + .value(requestContentData.getAdminControlType().name())); + filterQuery.add(termQuery._toQuery()); + } + if(requestContentData.provideEndTime()!=null && requestContentData.provideEndTime()!=null){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + RangeQuery rangeQuery=new RangeQuery.Builder() + .date(v->v.field("createDate") + .gte(requestContentData.provideStartTime().format(formatter)) + .lte(requestContentData.provideEndTime().format(formatter))) + .build(); + filterQuery.add(rangeQuery._toQuery()); + } + if(requestContentData.getIsReported()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("isReported") + .value(requestContentData.getIsReported())); + filterQuery.add(termQuery._toQuery()); + } + if(requestContentData.getStaticDataType()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("staticDataType") + .value(requestContentData.getStaticDataType().name())); + filterQuery.add(termQuery._toQuery()); + } + + return filterQuery; + } + private List makeMustQuery(ContentRequestDto.RequestContentData requestContentData){ + List mustQuery=new ArrayList<>(); + BoardSearchType boardSearchType=requestContentData.getBoardSearchType(); + String searchKeyWord=requestContentData.getSearchKeyWord(); + if(boardSearchType!=null){ + if(boardSearchType==BoardSearchType.CONTENT||boardSearchType==BoardSearchType.COMMENT){ + MatchQuery matchQuery=MatchQuery.of(m-> + m.field("content") + .query(searchKeyWord)); + mustQuery.add(matchQuery._toQuery()); + } + if(boardSearchType==BoardSearchType.TITLE_CONTENT){ + MultiMatchQuery multiMatchQuery=MultiMatchQuery.of( + m->m.fields(List.of("content","title")) + .query(searchKeyWord) + ); + mustQuery.add(multiMatchQuery._toQuery()); + } + if(boardSearchType==BoardSearchType.TITLE){ + MatchQuery matchQuery=MatchQuery.of(m-> + m.field("title") + .query(searchKeyWord)); + mustQuery.add(matchQuery._toQuery()); + } + if(requestContentData.getBoardSearchType().equals(BoardSearchType.NICKNAME)){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") + .query(requestContentData.getSearchKeyWord()) + .fuzziness("AUTO")); + mustQuery.add(matchQuery._toQuery()); + } + } + return mustQuery; + } + + + private ResponseContentSearch mappingDocToDto(ContentDocument contentDocument){ + Member member1=memberReadService.findByEmail(contentDocument.getEmail()); + String status=member1.getStatus().equals(MemberStatus.ACTIVE) ? "정상" : + member1.getStatus().equals(MemberStatus.WARNED) ? "경고" : + member1.getStatus().equals(MemberStatus.PENDING) ? "대기중":"정지"; + String reported=contentDocument.getIsReported() ? "신고" :"미신고"; + + String staticDataType=contentDocument.getStaticDataType().equals(StaticDataType.BOARD) ? "게시글": + contentDocument.getStaticDataType().equals(StaticDataType.COMMENT) ? "댓글" + : "채팅"; + Long reportNum=0L; + if(contentDocument.getIsReported()!=null&&contentDocument.getIsReported()) { + if (contentDocument.getStaticDataType().equals(StaticDataType.COMMENT)) { + reportNum = Optional.ofNullable(blazeJPAQueryFactory.select(report.count()) + .from(report) + .where(report.reportedContentId.eq(contentDocument.getContentId()) + .and(report.reportType.eq(ReportType.COMMENT))) + .fetchOne()) + .orElse(0L); + } + if (contentDocument.getStaticDataType().equals(StaticDataType.BOARD)) { + reportNum = Optional.ofNullable(blazeJPAQueryFactory.select(report.count()) + .from(report) + .where(report.reportedContentId.eq(contentDocument.getContentId()) + .and(report.reportType.eq(ReportType.BOARD))) + .fetchOne()) + .orElse(0L); + } + } + ResponseContentSearch responseContentSearch=new ResponseContentSearch( + contentDocument.getContentId(),member1.getNickname(),staticDataType, + contentDocument.getContent(),contentDocument.getCreateDate().toString(),status, + contentDocument.getAdminControlType().name(),reportNum,reported + ); + return responseContentSearch; + } +} diff --git a/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java b/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java index cc7ef8db..bae4bdce 100644 --- a/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java +++ b/src/main/java/org/myteam/server/admin/repository/ContentSearchRepository.java @@ -31,6 +31,7 @@ import org.myteam.server.member.domain.MemberStatus; import org.myteam.server.member.entity.Member; import org.myteam.server.member.service.MemberReadService; +import org.myteam.server.report.domain.Report; import org.myteam.server.report.domain.ReportType; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; @@ -70,9 +71,6 @@ public class ContentSearchRepository { private final JPAQueryFactory queryFactory; private final BlazeJPAQueryFactory blazeJPAQueryFactory; private final CreateAdminMemo createAdminMemo; - private final ElasticsearchOperations elasticsearchOperations; - private final MemberReadService memberReadService; - public void addAdminMemo(AdminMemoContentRequest adminMemoContentRequest) { createAdminMemo.createContentAdminMemo(adminMemoContentRequest,queryFactory); @@ -251,30 +249,6 @@ public Page getDataList(RequestContentData adminContentRe return getAdminBoardList(adminContentResearch); } - public List useElasticSearchForUnionQuery(RequestContentData requestContentData){ - List mustQuery=makeMustQuery(requestContentData); - List filterQuery=makeFilterQuery(requestContentData); - PageRequest pageRequest=PageRequest.of(requestContentData.getOffset(),10); - Query query=new BoolQuery.Builder() - .filter(filterQuery) - .must(mustQuery) - .build() - ._toQuery(); - NativeQuery nativeQuery=NativeQuery.builder() - .withQuery(query) - .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") - .order(SortOrder.Desc))))) - .withPageable(pageRequest) - .build(); - SearchHits datas= elasticsearchOperations.search(nativeQuery, ContentDocument.class); - List responseContentSearches=datas.stream().map(x->{ - return mappingDocToDto(x.getContent()); - }).collect(Collectors.toList()); - - DateFormatUtil.makeElasticTimeByFormatter(responseContentSearches,DateFormatEnum.formatByDotReq); - return responseContentSearches; - } - public Page getWhenDataTypeIsNullWithUnion(RequestContentData adminContentResearch) { BoardSearchType boardSearchType = adminContentResearch.getBoardSearchType(); @@ -764,95 +738,5 @@ private ResponseDetail editDataTimeAndAdminMemo(StaticDataType staticDataType, R return responseDetail; } - public List makeFilterQuery(RequestContentData requestContentData){ - List filterQuery=new ArrayList<>(); - if(requestContentData.getAdminControlType()!=null){ - TermQuery termQuery=TermQuery.of(t->t.field("adminControlType") - .value(requestContentData.getAdminControlType().name())); - filterQuery.add(termQuery._toQuery()); - } - if(requestContentData.provideEndTime()!=null && requestContentData.provideEndTime()!=null){ - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); - RangeQuery rangeQuery=new RangeQuery.Builder() - .date(v->v.field("createDate") - .gte(requestContentData.provideStartTime().format(formatter)) - .lte(requestContentData.provideEndTime().format(formatter))) - .build(); - filterQuery.add(rangeQuery._toQuery()); - } - if(requestContentData.getIsReported()!=null){ - if(requestContentData.getIsReported()) { - RangeQuery rangeQuery = new RangeQuery.Builder() - .number(v -> v.field("reportCount") - .gt(Double.valueOf("0"))) - .build(); - filterQuery.add(rangeQuery._toQuery()); - } - else{ - RangeQuery rangeQuery = new RangeQuery.Builder() - .number(v -> v.field("reportCount") - .lte(Double.valueOf("0"))) - .build(); - filterQuery.add(rangeQuery._toQuery()); - } - } - if(requestContentData.getStaticDataType()!=null){ - TermQuery termQuery=TermQuery.of(t->t.field("staticDataType") - .value(requestContentData.getStaticDataType().name())); - filterQuery.add(termQuery._toQuery()); - } - - return filterQuery; - } - public List makeMustQuery(RequestContentData requestContentData){ - List mustQuery=new ArrayList<>(); - BoardSearchType boardSearchType=requestContentData.getBoardSearchType(); - String searchKeyWord=requestContentData.getSearchKeyWord(); - if(boardSearchType!=null){ - if(boardSearchType==BoardSearchType.CONTENT||boardSearchType==BoardSearchType.COMMENT){ - MatchQuery matchQuery=MatchQuery.of(m-> - m.field("content") - .query(searchKeyWord)); - mustQuery.add(matchQuery._toQuery()); - } - if(boardSearchType==BoardSearchType.TITLE_CONTENT){ - MultiMatchQuery multiMatchQuery=MultiMatchQuery.of( - m->m.fields(List.of("content","title")) - .query(searchKeyWord) - ); - mustQuery.add(multiMatchQuery._toQuery()); - } - if(boardSearchType==BoardSearchType.TITLE){ - MatchQuery matchQuery=MatchQuery.of(m-> - m.field("title") - .query(searchKeyWord)); - mustQuery.add(matchQuery._toQuery()); - } - if(requestContentData.getBoardSearchType().equals(BoardSearchType.NICKNAME)){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") - .query(requestContentData.getSearchKeyWord()) - .fuzziness("AUTO")); - mustQuery.add(matchQuery._toQuery()); - } - } - return mustQuery; - } - - public ResponseContentSearch mappingDocToDto(ContentDocument contentDocument){ - Member member1=memberReadService.findByEmail(contentDocument.getEmail()); - String status=member1.getStatus().equals(MemberStatus.ACTIVE) ? "정상" : - member1.getStatus().equals(MemberStatus.WARNED) ? "경고" : - member1.getStatus().equals(MemberStatus.PENDING) ? "대기중":"정지"; - String reported=contentDocument.getReportCount()>0 ? "신고" :"미신고"; - String staticDataType=contentDocument.getStaticDataType().equals(StaticDataType.BOARD) ? "게시글": - contentDocument.getStaticDataType().equals(StaticDataType.COMMENT) ? "댓글" - : "채팅"; - ResponseContentSearch responseContentSearch=new ResponseContentSearch( - contentDocument.getContentId(),member1.getNickname(),staticDataType, - contentDocument.getContent(),contentDocument.getCreateDate().toString(),status, - contentDocument.getAdminControlType().name(),contentDocument.getReportCount(),reported - ); - return responseContentSearch; - } } diff --git a/src/main/java/org/myteam/server/admin/repository/ImproveElasticRepository.java b/src/main/java/org/myteam/server/admin/repository/ImproveElasticRepository.java new file mode 100644 index 00000000..36603462 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/repository/ImproveElasticRepository.java @@ -0,0 +1,118 @@ +package org.myteam.server.admin.repository; + +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.*; +import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.ImprovementDocument; +import org.myteam.server.admin.dto.request.ImproveRequestDto; +import org.myteam.server.admin.dto.response.ImprovementResponseDto; +import org.myteam.server.admin.utill.enums.DateFormatEnum; +import org.myteam.server.global.util.date.DateFormatUtil; +import org.myteam.server.improvement.domain.ImportantStatus; +import org.myteam.server.improvement.domain.ImprovementStatus; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.client.elc.NativeQuery; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.stereotype.Repository; + +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static org.myteam.server.admin.dto.response.ImprovementResponseDto.*; + +@RequiredArgsConstructor +@Repository +public class ImproveElasticRepository { + + + + private final ElasticsearchOperations elasticsearchOperations; + + public Page getImprovementByElasticSearch(ImproveRequestDto.RequestImprovementList requestImprovementList){ + List must=makeMustQuery(requestImprovementList); + List filter=filterQuery(requestImprovementList); + PageRequest pageRequest=PageRequest.of(requestImprovementList.getOffset(),10); + + Query query=new BoolQuery.Builder() + .filter(filter) + .must(must) + .build() + ._toQuery(); + + NativeQuery nativeQuery=NativeQuery.builder() + .withQuery(query) + .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") + .order(SortOrder.Desc))))) + .withPageable(pageRequest) + .build(); + SearchHits data=elasticsearchOperations.search(nativeQuery, ImprovementDocument.class); + + List improvements=data.stream().map(x->{ + ImprovementDocument doc=x.getContent(); + String importantStatus= doc.getImportantStatus().equals(ImportantStatus.LOW) ? "낮음" + :doc.getImportantStatus().equals(ImportantStatus.HIGH) ? "높음 ":"중간"; + String improveStatus=doc.getImprovementStatus().equals(ImprovementStatus.PENDING) ?"접수전" + :doc.getImprovementStatus().equals(ImprovementStatus.RECEIVED) ? "접수완료": "개선완료"; + return new ResponseImprovement( + doc.getId(), doc.getMemberId(),importantStatus,improveStatus,0 + ,doc.getNickName(),doc.getTitle(), + doc.getContent(),doc.getCreateDate().toString() + ); + }).collect(Collectors.toList()); + DateFormatUtil.makeElasticTimeByFormatter(improvements, DateFormatEnum.formatByDotReq); + return new PageImpl<>(improvements,pageRequest,data.getTotalHits()); + } + + private List filterQuery(ImproveRequestDto.RequestImprovementList requestImprovementList){ + List filter=new ArrayList<>(); + if(requestImprovementList.getImportantStatus()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("importantStatus") + .value(requestImprovementList.getImportantStatus().name())); + filter.add(termQuery._toQuery()); + } + if(requestImprovementList.getImprovementStatus()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("improvementStatus") + .value(requestImprovementList.getImprovementStatus().name())); + filter.add(termQuery._toQuery()); + } + if(requestImprovementList.provideEndTime()!=null&&requestImprovementList.provideStartTime()!=null){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + RangeQuery rangeQuery=RangeQuery.of(r->r.date( + v->v.field("createDate") + .gte(requestImprovementList.provideStartTime().format(formatter)) + .lt(requestImprovementList.provideEndTime().format(formatter)) + )); + filter.add(rangeQuery._toQuery()); + } + return filter; + } + + private List makeMustQuery(ImproveRequestDto.RequestImprovementList requestImprovementList){ + List mustQuery=new ArrayList<>(); + + if(requestImprovementList.getContent()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("content") + .query(requestImprovementList.getContent())); + mustQuery.add(matchQuery._toQuery()); + } + if(requestImprovementList.getTitle()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("title") + .query(requestImprovementList.getTitle())); + mustQuery.add(matchQuery._toQuery()); + } + if(requestImprovementList.getNickName()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") + .query(requestImprovementList.getNickName()) + .fuzziness("AUTO")); + mustQuery.add(matchQuery._toQuery()); + } + + return mustQuery; + } +} diff --git a/src/main/java/org/myteam/server/admin/repository/InquiryElasticRepository.java b/src/main/java/org/myteam/server/admin/repository/InquiryElasticRepository.java new file mode 100644 index 00000000..80730a20 --- /dev/null +++ b/src/main/java/org/myteam/server/admin/repository/InquiryElasticRepository.java @@ -0,0 +1,114 @@ +package org.myteam.server.admin.repository; + +import co.elastic.clients.elasticsearch._types.SortOptions; +import co.elastic.clients.elasticsearch._types.SortOrder; +import co.elastic.clients.elasticsearch._types.query_dsl.*; +import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.InquiryDocument; +import org.myteam.server.admin.utill.enums.DateFormatEnum; +import org.myteam.server.global.util.date.DateFormatUtil; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.elasticsearch.client.elc.NativeQuery; +import org.springframework.data.elasticsearch.core.ElasticsearchOperations; +import org.springframework.data.elasticsearch.core.SearchHits; +import org.springframework.stereotype.Repository; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import static org.myteam.server.admin.dto.request.InquiryRequestDto.*; +import static org.myteam.server.admin.dto.response.InquiryResponseDto.*; + +@Repository +@RequiredArgsConstructor +public class InquiryElasticRepository { + + private final ElasticsearchOperations elasticsearchOperations; + + public Page getInquiryListByContElasticSearch(RequestInquiryListCond requestInquiryListCond){ + List filter=makeFilterQuery(requestInquiryListCond); + List must=makeMustQuery(requestInquiryListCond); + PageRequest pageRequest=PageRequest.of(requestInquiryListCond.getOffset(),10); + + Query query=new BoolQuery.Builder() + .filter(filter) + .must(must) + .build() + ._toQuery(); + + NativeQuery nativeQuery=NativeQuery.builder() + .withQuery(query) + .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") + .order(SortOrder.Desc))))) + .withPageable(pageRequest) + .build(); + SearchHits data=elasticsearchOperations.search(nativeQuery, InquiryDocument.class); + + List responseInquiryListConds=data.stream().map(x->{ + InquiryDocument doc=x.getContent(); + String isAnswered= doc.getIsAdminAnswered() ? "답변완료" :"답변대기"; + String isMember=doc.getIsMember() ? "회원":"비회원"; + String nicknameEmail=doc.getNickName()==null ? doc.getEmail() : doc.getNickName(); + + return new ResponseInquiryListCond( + doc.getId(),isAnswered,isMember,nicknameEmail,doc.getContent(),doc.getEmail(), + doc.getCreateDate().toString() + ); + }).collect(Collectors.toList()); + + DateFormatUtil.makeElasticTimeByFormatter(responseInquiryListConds, DateFormatEnum.formatByDotReq); + + return new PageImpl<>(responseInquiryListConds,pageRequest,data.getTotalHits()); + + } + + private List makeFilterQuery(RequestInquiryListCond requestInquiryListCond){ + List filterQuery=new ArrayList<>(); + if(requestInquiryListCond.getIsMember()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("isMember") + .value(requestInquiryListCond.getIsMember())); + filterQuery.add(termQuery._toQuery()); + } + if(requestInquiryListCond.getIsAnswered()!=null){ + TermQuery termQuery=TermQuery.of(t->t.field("isAdminAnswered") + .value(requestInquiryListCond.getIsAnswered())); + filterQuery.add(termQuery._toQuery()); + } + if(requestInquiryListCond.provideStartTime()!=null&&requestInquiryListCond.provideEndTime()!=null){ + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); + RangeQuery rangeQuery=RangeQuery.of(r->r.date( + v->v.field("createDate") + .gte(requestInquiryListCond.provideStartTime().format(formatter)) + .lt(requestInquiryListCond.provideEndTime().format(formatter)) + )); + filterQuery.add(rangeQuery._toQuery()); + } + if(requestInquiryListCond.getEmail()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("email") + .query(requestInquiryListCond.getEmail()) + .fuzziness("AUTO")); + filterQuery.add(matchQuery._toQuery()); + } + + return filterQuery; + } + private List makeMustQuery(RequestInquiryListCond requestInquiryListCond){ + List mustQuery=new ArrayList<>(); + + if(requestInquiryListCond.getContent()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("content") + .query(requestInquiryListCond.getContent())); + mustQuery.add(matchQuery._toQuery()); + } + + if(requestInquiryListCond.getNickName()!=null){ + MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") + .query(requestInquiryListCond.getNickName()) + .fuzziness("AUTO")); + mustQuery.add(matchQuery._toQuery()); + } + return mustQuery; + } +} diff --git a/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java b/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java index 76c1044f..0bed1454 100644 --- a/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java +++ b/src/main/java/org/myteam/server/admin/repository/InquirySearchRepo.java @@ -48,8 +48,6 @@ public class InquirySearchRepo { private final JPAQueryFactory queryFactory; private final CreateAdminMemo createAdminMemo; - private final ElasticsearchOperations elasticsearchOperations; - public AdminContentMemo createAdminMemo(AdminMemoInquiryRequest adminMemoRequest) { return createAdminMemo.createInquiryAdminMemo(adminMemoRequest, queryFactory); @@ -192,42 +190,7 @@ public Page getInquiryListByCond(RequestInquiryListCond return new PageImpl<>(responseInquiryListConds, pageable, count); } - public List getInquiryListByContElasticSearch(RequestInquiryListCond requestInquiryListCond){ - List filter=makeFilterQuery(requestInquiryListCond); - List must=makeMustQuery(requestInquiryListCond); - PageRequest pageRequest=PageRequest.of(requestInquiryListCond.getOffset(),10); - - Query query=new BoolQuery.Builder() - .filter(filter) - .must(must) - .build() - ._toQuery(); - - NativeQuery nativeQuery=NativeQuery.builder() - .withQuery(query) - .withSort(List.of(SortOptions.of(s->s.field(f->f.field("createDate") - .order(SortOrder.Desc))))) - .withPageable(pageRequest) - .build(); - SearchHits data=elasticsearchOperations.search(nativeQuery, InquiryDocument.class); - - List responseInquiryListConds=data.stream().map(x->{ - InquiryDocument doc=x.getContent(); - String isAnswered= doc.getIsAdminAnswered() ? "답변완료" :"답변대기"; - String isMember=doc.getIsMember() ? "회원":"비회원"; - String nicknameEmail=doc.getNickName()==null ? doc.getEmail() : doc.getNickName(); - - return new ResponseInquiryListCond( - doc.getId(),isAnswered,isMember,nicknameEmail,doc.getContent(),doc.getEmail(), - doc.getCreateDate().toString() - ); - }).collect(Collectors.toList()); - - DateFormatUtil.makeElasticTimeByFormatter(responseInquiryListConds,DateFormatEnum.formatByDotReq); - - return responseInquiryListConds; - } private Predicate memberOrNot(Boolean isMember) { @@ -290,53 +253,7 @@ private Predicate searchByTimeLine(LocalDateTime startTime, LocalDateTime endTim } - private List makeFilterQuery(RequestInquiryListCond requestInquiryListCond){ - List filterQuery=new ArrayList<>(); - if(requestInquiryListCond.getIsMember()!=null){ - TermQuery termQuery=TermQuery.of(t->t.field("isMember") - .value(requestInquiryListCond.getIsMember())); - filterQuery.add(termQuery._toQuery()); - } - if(requestInquiryListCond.getIsAnswered()!=null){ - TermQuery termQuery=TermQuery.of(t->t.field("isAdminAnswered") - .value(requestInquiryListCond.getIsAnswered())); - filterQuery.add(termQuery._toQuery()); - } - if(requestInquiryListCond.provideStartTime()!=null&&requestInquiryListCond.provideEndTime()!=null){ - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss"); - RangeQuery rangeQuery=RangeQuery.of(r->r.date( - v->v.field("createDate") - .gte(requestInquiryListCond.provideStartTime().format(formatter)) - .lt(requestInquiryListCond.provideEndTime().format(formatter)) - )); - filterQuery.add(rangeQuery._toQuery()); - } - if(requestInquiryListCond.getEmail()!=null){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("email") - .query(requestInquiryListCond.getEmail()) - .fuzziness("AUTO")); - filterQuery.add(matchQuery._toQuery()); - } - - return filterQuery; - } - public List makeMustQuery(RequestInquiryListCond requestInquiryListCond){ - List mustQuery=new ArrayList<>(); - - if(requestInquiryListCond.getContent()!=null){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("content") - .query(requestInquiryListCond.getContent())); - mustQuery.add(matchQuery._toQuery()); - } - if(requestInquiryListCond.getNickName()!=null){ - MatchQuery matchQuery=MatchQuery.of(m->m.field("nickName") - .query(requestInquiryListCond.getNickName()) - .fuzziness("AUTO")); - mustQuery.add(matchQuery._toQuery()); - } - return mustQuery; - } } diff --git a/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java index 40a22fa4..e7731680 100644 --- a/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java +++ b/src/main/java/org/myteam/server/admin/repository/simpleRepo/ElasticContentRepository.java @@ -1,7 +1,11 @@ package org.myteam.server.admin.repository.simpleRepo; import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.utill.enums.StaticDataType; import org.springframework.data.elasticsearch.repository.ElasticsearchRepository; +import java.util.Optional; + public interface ElasticContentRepository extends ElasticsearchRepository { + Optional findByContentIdAndStaticDataType(Long contentId, StaticDataType staticDataType); } diff --git a/src/main/java/org/myteam/server/global/elastic/ElasticSearchSaveHandler.java b/src/main/java/org/myteam/server/global/elastic/ElasticSearchSaveHandler.java new file mode 100644 index 00000000..071210e4 --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/ElasticSearchSaveHandler.java @@ -0,0 +1,60 @@ +package org.myteam.server.global.elastic; + + +import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.document.ImprovementDocument; +import org.myteam.server.admin.document.InquiryDocument; +import org.myteam.server.admin.repository.simpleRepo.ElasticContentRepository; +import org.myteam.server.admin.repository.simpleRepo.ElasticImproverRepository; +import org.myteam.server.admin.repository.simpleRepo.ElasticInquiryRepository; +import org.myteam.server.global.elastic.event.*; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionPhase; +import org.springframework.transaction.event.TransactionalEventListener; + +@RequiredArgsConstructor +@Component +public class ElasticSearchSaveHandler { + + private final ElasticContentRepository elasticContentRepository; + private final ElasticImproverRepository elasticImproverRepository; + private final ElasticInquiryRepository elasticInquiryRepository; + + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void saveContentAfterCommit(ElasticContentEvent contentEvent){ + elasticContentRepository.save(contentEvent.getDoc()); + } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void saveInquiryAfterCommit(ElasticInquiryEvent inquiryEvent){ + elasticInquiryRepository.save(inquiryEvent.getDoc()); + } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void saveImproveAfterCommit(ElasticImproveEvent improveEvent){ + elasticImproverRepository.save(improveEvent.getDoc()); + } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void updateContentAfterCommit(ElasticContentUpdateEvent contentEvent){ + ContentDocument contentDocument= + elasticContentRepository.findByContentIdAndStaticDataType(contentEvent.getContentId(),contentEvent.getStaticDataType()).get(); + ContentDocument toUpdateDoc=contentEvent.updateDoc(contentDocument); + elasticContentRepository.save(toUpdateDoc); + + } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void updateInquiryAfterCommit(ElasticInquiryUpdateEvent inquiryEvent){ + InquiryDocument inquiryDocument= + elasticInquiryRepository.findById(inquiryEvent.getId()).get(); + InquiryDocument toUpdateDoc=inquiryEvent.updateDoc(inquiryDocument); + elasticInquiryRepository.save(toUpdateDoc); + } + @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) + public void updateImproveAfterCommit(ElasticImproveUpdateEvent improveEvent){ + ImprovementDocument improvementDocument= + elasticImproverRepository.findById(improveEvent.getId()).get(); + ImprovementDocument toUpdateDoc=improveEvent.updateDoc(improvementDocument); + elasticImproverRepository.save(toUpdateDoc); + } + + +} diff --git a/src/main/java/org/myteam/server/global/elastic/event/ElasticContentEvent.java b/src/main/java/org/myteam/server/global/elastic/event/ElasticContentEvent.java new file mode 100644 index 00000000..d50a6d5d --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/event/ElasticContentEvent.java @@ -0,0 +1,60 @@ +package org.myteam.server.global.elastic.event; + + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.utill.enums.AdminControlType; +import org.myteam.server.admin.utill.enums.StaticDataType; +import org.springframework.data.annotation.Id; +import org.springframework.data.elasticsearch.annotations.DateFormat; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +public class ElasticContentEvent { + + private String email; + private String nickName; + private StaticDataType staticDataType; + private AdminControlType adminControlType; + private Boolean isReported; + private Long contentId; + private String title; + private String content; + private LocalDateTime createDate; + + + @Builder + public ElasticContentEvent(String email, String nickName, StaticDataType staticDataType, + AdminControlType adminControlType, Boolean isReported, Long contentId, + String title, String content, LocalDateTime createDate) { + this.email = email; + this.nickName = nickName; + this.staticDataType = staticDataType; + this.adminControlType = adminControlType; + this.isReported=isReported; + this.contentId = contentId; + this.title = title; + this.content = content; + this.createDate = createDate; + } + + public ContentDocument getDoc(){ + return ContentDocument.builder() + .email(this.email) + .nickName(this.nickName) + .staticDataType(this.staticDataType) + .adminControlType(this.adminControlType) + .isReported(this.isReported) + .contentId(this.contentId) + .title(this.title) + .content(this.content) + .createDate(this.createDate) + .build(); + } +} diff --git a/src/main/java/org/myteam/server/global/elastic/event/ElasticContentUpdateEvent.java b/src/main/java/org/myteam/server/global/elastic/event/ElasticContentUpdateEvent.java new file mode 100644 index 00000000..1706e681 --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/event/ElasticContentUpdateEvent.java @@ -0,0 +1,54 @@ +package org.myteam.server.global.elastic.event; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.admin.document.ContentDocument; +import org.myteam.server.admin.utill.enums.AdminControlType; +import org.myteam.server.admin.utill.enums.StaticDataType; + + +@Getter +@NoArgsConstructor +public class ElasticContentUpdateEvent { + + private StaticDataType staticDataType; + private String nickName; + private AdminControlType adminControlType; + private Boolean isReported; + private Long contentId; + private String title; + private String content; + + + public ElasticContentUpdateEvent(StaticDataType staticDataType, String nickName, AdminControlType adminControlType, + Boolean isReported, Long contentId, String title, String content) { + this.staticDataType = staticDataType; + this.nickName = nickName; + this.adminControlType = adminControlType; + this.isReported = isReported; + this.contentId = contentId; + this.title = title; + this.content = content; + } + + @Builder + + + public ContentDocument updateDoc(ContentDocument doc){ + return ContentDocument.builder() + .id(doc.getId()) + .email(doc.getEmail()) + .nickName(this.nickName!=null ? this.nickName:doc.getNickName()) + .staticDataType(doc.getStaticDataType()) + .adminControlType(this.adminControlType!=null ? this.adminControlType:doc.getAdminControlType()) + .isReported(this.isReported!=null ? this.isReported :doc.getIsReported()) + .contentId(doc.getContentId()) + .title(this.title!=null? this.title:doc.getTitle()) + .content(this.content!=null? this.content:doc.getContent()) + .createDate(doc.getCreateDate()) + .build(); + } + + +} diff --git a/src/main/java/org/myteam/server/global/elastic/event/ElasticImproveEvent.java b/src/main/java/org/myteam/server/global/elastic/event/ElasticImproveEvent.java new file mode 100644 index 00000000..8f335279 --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/event/ElasticImproveEvent.java @@ -0,0 +1,55 @@ +package org.myteam.server.global.elastic.event; + +import jakarta.persistence.Id; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.admin.document.ImprovementDocument; +import org.myteam.server.improvement.domain.ImportantStatus; +import org.myteam.server.improvement.domain.ImprovementStatus; +import org.springframework.data.elasticsearch.annotations.DateFormat; +import org.springframework.data.elasticsearch.annotations.Field; +import org.springframework.data.elasticsearch.annotations.FieldType; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class ElasticImproveEvent { + + + public Long id; + private UUID memberId; + private String title; + private String content; + private String nickName; + private ImprovementStatus improvementStatus; + private ImportantStatus importantStatus; + private LocalDateTime createDate; + @Builder + public ElasticImproveEvent(Long id, UUID memberId, String title, String content, String nickName, + ImprovementStatus improvementStatus, ImportantStatus importantStatus, + LocalDateTime createDate) { + this.id = id; + this.memberId = memberId; + this.title = title; + this.content = content; + this.nickName = nickName; + this.improvementStatus = improvementStatus; + this.importantStatus = importantStatus; + this.createDate = createDate; + } + public ImprovementDocument getDoc(){ + return ImprovementDocument.builder() + .id(this.id) + .content(this.content) + .nickName(this.nickName) + .title(this.title) + .improvementStatus(this.improvementStatus) + .importantStatus(this.importantStatus) + .memberId(this.memberId) + .createDate(this.createDate) + .build(); + } +} diff --git a/src/main/java/org/myteam/server/global/elastic/event/ElasticImproveUpdateEvent.java b/src/main/java/org/myteam/server/global/elastic/event/ElasticImproveUpdateEvent.java new file mode 100644 index 00000000..1bdb0748 --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/event/ElasticImproveUpdateEvent.java @@ -0,0 +1,48 @@ +package org.myteam.server.global.elastic.event; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.admin.document.ImprovementDocument; +import org.myteam.server.improvement.domain.ImportantStatus; +import org.myteam.server.improvement.domain.ImprovementStatus; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Getter +@NoArgsConstructor +public class ElasticImproveUpdateEvent { + + private Long id; + private String title; + private String content; + private String nickName; + private ImprovementStatus improvementStatus; + private ImportantStatus importantStatus; + + public ElasticImproveUpdateEvent(Long id, String title, String content, String nickName, + ImprovementStatus improvementStatus, ImportantStatus importantStatus) { + this.id = id; + this.title = title; + this.content = content; + this.nickName = nickName; + this.improvementStatus = improvementStatus; + this.importantStatus = importantStatus; + } + + @Builder + + public ImprovementDocument updateDoc(ImprovementDocument doc){ + return ImprovementDocument.builder() + .id(doc.getId()) + .content(this.content!=null ? this.content:doc.getContent()) + .nickName(this.nickName!=null? this.nickName: doc.getNickName()) + .title(this.title!=null? this.title:doc.getTitle()) + .improvementStatus(this.improvementStatus!=null? this.improvementStatus:doc.getImprovementStatus()) + .importantStatus(this.importantStatus!=null? this.importantStatus:doc.getImportantStatus()) + .memberId(doc.getMemberId()) + .createDate(doc.getCreateDate()) + .build(); + } +} diff --git a/src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryEvent.java b/src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryEvent.java new file mode 100644 index 00000000..ae8c4d9f --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryEvent.java @@ -0,0 +1,45 @@ +package org.myteam.server.global.elastic.event; + +import jakarta.persistence.Id; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.myteam.server.admin.document.InquiryDocument; + +import java.time.LocalDateTime; + +@Getter +@NoArgsConstructor +public class ElasticInquiryEvent { + + private Long id; + private String content; + private String nickName; + private LocalDateTime createDate; + private String email; + private Boolean isAdminAnswered; + private Boolean isMember; + + @Builder + public ElasticInquiryEvent(Long id, String content, String nickName, LocalDateTime createDate, + String email, Boolean isAdminAnswered, Boolean isMember) { + this.id = id; + this.content = content; + this.nickName = nickName; + this.createDate = createDate; + this.email = email; + this.isAdminAnswered = isAdminAnswered; + this.isMember = isMember; + } + public InquiryDocument getDoc(){ + return InquiryDocument.builder() + .id(this.id) + .email(this.email) + .createDate(this.createDate) + .isAdminAnswered(this.isAdminAnswered) + .content(this.content) + .nickName(this.nickName) + .isMember(this.isMember) + .build(); + } +} diff --git a/src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryUpdateEvent.java b/src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryUpdateEvent.java new file mode 100644 index 00000000..b4386fb0 --- /dev/null +++ b/src/main/java/org/myteam/server/global/elastic/event/ElasticInquiryUpdateEvent.java @@ -0,0 +1,45 @@ +package org.myteam.server.global.elastic.event; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.RequiredArgsConstructor; +import org.myteam.server.admin.document.InquiryDocument; + +import java.time.LocalDateTime; + +@NoArgsConstructor +@Getter +public class ElasticInquiryUpdateEvent { + + private Long id; + private String content; + private String nickName; + private Boolean isAdminAnswered; + private Boolean isMember; + + + @Builder + public ElasticInquiryUpdateEvent(Long id, String content, String nickName, + Boolean isAdminAnswered, Boolean isMember) { + this.id = id; + this.content = content; + this.nickName = nickName; + this.isAdminAnswered = isAdminAnswered; + this.isMember = isMember; + } + + + + public InquiryDocument updateDoc(InquiryDocument doc){ + return InquiryDocument.builder() + .id(doc.getId()) + .email(doc.getEmail()) + .createDate(doc.getCreateDate()) + .isAdminAnswered(this.isAdminAnswered!=null ? this.isAdminAnswered :doc.getIsAdminAnswered()) + .content(this.content!=null ? this.content : doc.getContent()) + .nickName(this.nickName!=null ? this.nickName : doc.getNickName()) + .isMember(this.isMember!=null? this.isMember:doc.getIsMember()) + .build(); + } +} diff --git a/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java b/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java index e3c1a9bd..69123ef6 100644 --- a/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java +++ b/src/test/java/org/myteam/server/admin/repository/ElasticSearchTest.java @@ -49,10 +49,12 @@ import java.util.List; import static org.myteam.server.admin.dto.request.ContentRequestDto.*; +import static org.myteam.server.admin.dto.response.ImprovementResponseDto.*; +import static org.myteam.server.admin.dto.response.InquiryResponseDto.*; import static org.myteam.server.admin.dto.response.ResponseContentDto.*; import static org.myteam.server.board.domain.QBoard.board; -@SpringBootTest +//@SpringBootTest public class ElasticSearchTest extends IntegrationTestSupport { static private DataSource testDataSource; @@ -64,7 +66,13 @@ public class ElasticSearchTest extends IntegrationTestSupport { AdminImprovementSearchRepo adminImprovementSearchRepo; @Autowired - JPAQueryFactory queryFactory; + InquiryElasticRepository inquiryElasticRepository; + + @Autowired + ImproveElasticRepository improveElasticRepository; + + @Autowired + ContentElasticRepository contentElasticRepository; Member m; //@BeforeAll @@ -103,7 +111,7 @@ void setBeforeTest(){ .contentId(b.getId()) .content(b.getContent()) .createDate(b.getCreateDate()) - .reportCount(0L) + .isReported(false) .email(m.getEmail()) .build(); InquiryDocument inquiryDoc=InquiryDocument.builder() @@ -141,7 +149,7 @@ void setBeforeTest(){ .contentId(b.getId()) .content(b.getContent()) .createDate(b.getCreateDate()) - .reportCount(0L) + .isReported(false) .email(m.getEmail()) .build(); elasticContentRepository.save(c); @@ -169,9 +177,9 @@ void contentTest(){ .reported(false) .offset(1) .build(); - List responseContentSearches - =contentSearchRepository.useElasticSearchForUnionQuery(requestContentData); - Assertions.assertThat(responseContentSearches.size()).isEqualTo(5); + Page responseContentSearches + =contentElasticRepository.useElasticSearchForUnionQuery(requestContentData); + Assertions.assertThat(responseContentSearches.getSize()).isEqualTo(5); @@ -185,10 +193,10 @@ void contentTest(){ .offset(1) .build(); - List responseImprovements - =adminImprovementSearchRepo.getImprovementByElasticSearch(requestImprovementList); + Page responseImprovements + =improveElasticRepository.getImprovementByElasticSearch(requestImprovementList); - Assertions.assertThat(responseImprovements.size()).isEqualTo(5); + Assertions.assertThat(responseImprovements.getSize()).isEqualTo(5); InquiryRequestDto.RequestInquiryListCond requestInquiryListCond= InquiryRequestDto.RequestInquiryListCond.builder() @@ -199,9 +207,9 @@ void contentTest(){ .email(m.getEmail()) .build(); - List responseInquiryLists - =inquirySearchRepo.getInquiryListByContElasticSearch(requestInquiryListCond); - Assertions.assertThat(responseInquiryLists.size()).isEqualTo(5); + Page responseInquiryLists + =inquiryElasticRepository.getInquiryListByContElasticSearch(requestInquiryListCond); + Assertions.assertThat(responseInquiryLists.getSize()).isEqualTo(5); }