From e44f146226c0428dd4c4a470ac5a1efa5459fec7 Mon Sep 17 00:00:00 2001 From: seungyeop-lee Date: Mon, 13 May 2024 16:45:22 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EA=B8=B0=EC=A1=B4=20model=20=EB=B0=8F?= =?UTF-8?q?=20logic=EC=9D=84=20=EB=8D=B0=EB=AA=A8=20=EC=A0=84=EC=9A=A9?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20#42?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ository.java => DemoSearchRepository.java} | 28 ++--- .../java/vook/server/api/app/DemoService.java | 31 +++++ .../vook/server/api/app/GlossaryService.java | 24 ---- .../java/vook/server/api/app/TermService.java | 20 ---- .../server/api/devhelper/InitService.java | 49 ++++---- .../vook/server/api/devhelper/LocalInit.java | 6 +- .../server/api/model/GlossaryRepository.java | 9 -- .../java/vook/server/api/model/Member.java | 28 ----- .../server/api/model/MemberRepository.java | 6 - .../main/java/vook/server/api/model/Term.java | 55 --------- .../vook/server/api/model/TermRepository.java | 6 - .../api/model/TermSynonymRepository.java | 6 - .../{Glossary.java => demo/DemoGlossary.java} | 21 ++-- .../model/demo/DemoGlossaryRepository.java | 9 ++ .../vook/server/api/model/demo/DemoTerm.java | 56 +++++++++ .../api/model/demo/DemoTermRepository.java | 6 + .../DemoTermSynonym.java} | 20 ++-- .../model/demo/DemoTermSynonymRepository.java | 6 + ...hParams.java => DemoTermSearchParams.java} | 6 +- .../outbound/search/DemoTermSearchResult.java | 23 ++++ .../search/DemoTermSearchService.java | 99 ++++++++++++++++ .../outbound/search/MeilisearchService.java | 109 +++--------------- .../api/outbound/search/SearchClearable.java | 5 - .../api/outbound/search/SearchResult.java | 23 ---- .../api/outbound/search/SearchService.java | 14 --- .../api/web/routes/demo/DemoWebService.java | 28 +++-- .../reqres/RetrieveGlossariesResponse.java | 6 +- .../demo/reqres/RetrieveTermsResponse.java | 15 ++- .../routes/demo/reqres/SearchTermRequest.java | 10 +- .../demo/reqres/SearchTermResponse.java | 12 +- 30 files changed, 336 insertions(+), 400 deletions(-) rename api/src/main/java/vook/server/api/app/{TermSearchRepository.java => DemoSearchRepository.java} (61%) create mode 100644 api/src/main/java/vook/server/api/app/DemoService.java delete mode 100644 api/src/main/java/vook/server/api/app/GlossaryService.java delete mode 100644 api/src/main/java/vook/server/api/app/TermService.java delete mode 100644 api/src/main/java/vook/server/api/model/GlossaryRepository.java delete mode 100644 api/src/main/java/vook/server/api/model/Member.java delete mode 100644 api/src/main/java/vook/server/api/model/MemberRepository.java delete mode 100644 api/src/main/java/vook/server/api/model/Term.java delete mode 100644 api/src/main/java/vook/server/api/model/TermRepository.java delete mode 100644 api/src/main/java/vook/server/api/model/TermSynonymRepository.java rename api/src/main/java/vook/server/api/model/{Glossary.java => demo/DemoGlossary.java} (56%) create mode 100644 api/src/main/java/vook/server/api/model/demo/DemoGlossaryRepository.java create mode 100644 api/src/main/java/vook/server/api/model/demo/DemoTerm.java create mode 100644 api/src/main/java/vook/server/api/model/demo/DemoTermRepository.java rename api/src/main/java/vook/server/api/model/{TermSynonym.java => demo/DemoTermSynonym.java} (50%) create mode 100644 api/src/main/java/vook/server/api/model/demo/DemoTermSynonymRepository.java rename api/src/main/java/vook/server/api/outbound/search/{SearchParams.java => DemoTermSearchParams.java} (89%) create mode 100644 api/src/main/java/vook/server/api/outbound/search/DemoTermSearchResult.java create mode 100644 api/src/main/java/vook/server/api/outbound/search/DemoTermSearchService.java delete mode 100644 api/src/main/java/vook/server/api/outbound/search/SearchClearable.java delete mode 100644 api/src/main/java/vook/server/api/outbound/search/SearchResult.java delete mode 100644 api/src/main/java/vook/server/api/outbound/search/SearchService.java diff --git a/api/src/main/java/vook/server/api/app/TermSearchRepository.java b/api/src/main/java/vook/server/api/app/DemoSearchRepository.java similarity index 61% rename from api/src/main/java/vook/server/api/app/TermSearchRepository.java rename to api/src/main/java/vook/server/api/app/DemoSearchRepository.java index 3ee1bbb..a0aa82d 100644 --- a/api/src/main/java/vook/server/api/app/TermSearchRepository.java +++ b/api/src/main/java/vook/server/api/app/DemoSearchRepository.java @@ -6,42 +6,42 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Repository; import vook.server.api.helper.QuerydslHelper; -import vook.server.api.model.QTerm; -import vook.server.api.model.Term; +import vook.server.api.model.demo.DemoTerm; +import vook.server.api.model.demo.QDemoTerm; import java.util.List; @Repository @RequiredArgsConstructor -public class TermSearchRepository { +public class DemoSearchRepository { private final JPAQueryFactory queryFactory; - public List search(String glossaryUid, Pageable pageable) { - QTerm term = QTerm.term1; + public List searchDemoTerm(String demoGlossaryUid, Pageable pageable) { + QDemoTerm demoTerm = QDemoTerm.demoTerm; // fetch join과 pagination을 같이 하면, // HHH90003004: firstResult/maxResults specified with collection fetch; applying in memory // 에러가 발생, 이를 피하기 위해 pagination이 포함된 쿼리를 서브 쿼리로 하여 수행 JPAQuery termIdQuery = queryFactory - .select(term.id) - .from(term) - .where(term.glossary.uid.eq(glossaryUid)) + .select(demoTerm.id) + .from(demoTerm) + .where(demoTerm.demoGlossary.uid.eq(demoGlossaryUid)) .offset(pageable.getOffset()) .limit(pageable.getPageSize()); QuerydslHelper - .toOrderSpecifiers(term, pageable) + .toOrderSpecifiers(demoTerm, pageable) .forEach(termIdQuery::orderBy); - JPAQuery dataQuery = queryFactory - .selectFrom(term) - .leftJoin(term.synonyms).fetchJoin() - .where(term.id.in(termIdQuery)); + JPAQuery dataQuery = queryFactory + .selectFrom(demoTerm) + .leftJoin(demoTerm.synonyms).fetchJoin() + .where(demoTerm.id.in(termIdQuery)); // In 절에 들어간 입력순대로 출력되지 않음으로 정렬 조건을 다시 한번 설정 QuerydslHelper - .toOrderSpecifiers(term, pageable) + .toOrderSpecifiers(demoTerm, pageable) .forEach(dataQuery::orderBy); return dataQuery.fetch(); diff --git a/api/src/main/java/vook/server/api/app/DemoService.java b/api/src/main/java/vook/server/api/app/DemoService.java new file mode 100644 index 0000000..f593361 --- /dev/null +++ b/api/src/main/java/vook/server/api/app/DemoService.java @@ -0,0 +1,31 @@ +package vook.server.api.app; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import vook.server.api.model.demo.DemoGlossary; +import vook.server.api.model.demo.DemoGlossaryRepository; +import vook.server.api.model.demo.DemoTerm; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class DemoService { + + private final DemoGlossaryRepository demoGlossaryRepository; + private final DemoSearchRepository searchRepository; + + public List findAllDemoGlossary() { + return demoGlossaryRepository.findAll(); + } + + public Optional findDemoGlossaryByUid(String demoGlossaryUid) { + return demoGlossaryRepository.findByUid(demoGlossaryUid); + } + + public List findAllDemoTermBy(DemoGlossary demoGlossary, Pageable pageable) { + return searchRepository.searchDemoTerm(demoGlossary.getUid(), pageable); + } +} diff --git a/api/src/main/java/vook/server/api/app/GlossaryService.java b/api/src/main/java/vook/server/api/app/GlossaryService.java deleted file mode 100644 index 3e4815e..0000000 --- a/api/src/main/java/vook/server/api/app/GlossaryService.java +++ /dev/null @@ -1,24 +0,0 @@ -package vook.server.api.app; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import vook.server.api.model.Glossary; -import vook.server.api.model.GlossaryRepository; - -import java.util.List; -import java.util.Optional; - -@Service -@RequiredArgsConstructor -public class GlossaryService { - - private final GlossaryRepository repository; - - public List findAll() { - return repository.findAll(); - } - - public Optional findByUid(String uid) { - return repository.findByUid(uid); - } -} diff --git a/api/src/main/java/vook/server/api/app/TermService.java b/api/src/main/java/vook/server/api/app/TermService.java deleted file mode 100644 index 2e99799..0000000 --- a/api/src/main/java/vook/server/api/app/TermService.java +++ /dev/null @@ -1,20 +0,0 @@ -package vook.server.api.app; - -import lombok.RequiredArgsConstructor; -import org.springframework.data.domain.Pageable; -import org.springframework.stereotype.Service; -import vook.server.api.model.Glossary; -import vook.server.api.model.Term; - -import java.util.List; - -@Service -@RequiredArgsConstructor -public class TermService { - - private final TermSearchRepository searchRepository; - - public List findAllBy(Glossary glossary, Pageable pageable) { - return searchRepository.search(glossary.getUid(), pageable); - } -} diff --git a/api/src/main/java/vook/server/api/devhelper/InitService.java b/api/src/main/java/vook/server/api/devhelper/InitService.java index aa417c1..5869e57 100644 --- a/api/src/main/java/vook/server/api/devhelper/InitService.java +++ b/api/src/main/java/vook/server/api/devhelper/InitService.java @@ -5,9 +5,8 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import vook.server.api.model.*; -import vook.server.api.outbound.search.SearchClearable; -import vook.server.api.outbound.search.SearchService; +import vook.server.api.model.demo.*; +import vook.server.api.outbound.search.DemoTermSearchService; import java.io.IOException; import java.io.InputStream; @@ -21,38 +20,32 @@ public class InitService { private final ResourceLoader resourceLoader; - private final MemberRepository memberRepository; - private final GlossaryRepository glossaryRepository; - private final TermRepository termRepository; - private final TermSynonymRepository termSynonymRepository; - private final SearchClearable searchClearable; - - private final SearchService searchService; + private final DemoGlossaryRepository demoGlossaryRepository; + private final DemoTermRepository demoTermRepository; + private final DemoTermSynonymRepository demoTermSynonymRepository; + private final DemoTermSearchService searchService; public void init() { - termSynonymRepository.deleteAllInBatch(); - termRepository.deleteAllInBatch(); - glossaryRepository.deleteAllInBatch(); - memberRepository.deleteAllInBatch(); - searchClearable.clearAll(); - - Member vook = memberRepository.save(Member.forCreateOf("vook")); + demoTermSynonymRepository.deleteAllInBatch(); + demoTermRepository.deleteAllInBatch(); + demoGlossaryRepository.deleteAllInBatch(); + searchService.clearAll(); - Glossary devGlossary = glossaryRepository.save(Glossary.forCreateOf("개발", vook)); + DemoGlossary devGlossary = demoGlossaryRepository.save(DemoGlossary.forCreateOf("개발")); searchService.createGlossary(devGlossary); - Glossary designGlossary = glossaryRepository.save(Glossary.forCreateOf("디자인", vook)); + DemoGlossary designGlossary = demoGlossaryRepository.save(DemoGlossary.forCreateOf("디자인")); searchService.createGlossary(designGlossary); - Glossary marketingGlossary = glossaryRepository.save(Glossary.forCreateOf("마케팅", vook)); + DemoGlossary marketingGlossary = demoGlossaryRepository.save(DemoGlossary.forCreateOf("마케팅")); searchService.createGlossary(marketingGlossary); - Glossary practiceGlossary = glossaryRepository.save(Glossary.forCreateOf("실무", vook)); + DemoGlossary practiceGlossary = demoGlossaryRepository.save(DemoGlossary.forCreateOf("실무")); searchService.createGlossary(practiceGlossary); - List devTerms = getTerms("classpath:init/개발.tsv", devGlossary); - List terms = termRepository.saveAll(devTerms); - searchService.addTerms(terms, devGlossary); + List devTerms = getTerms("classpath:init/개발.tsv", devGlossary); + List terms = demoTermRepository.saveAll(devTerms); + searchService.addTerms(devGlossary, terms); } - private List getTerms(String location, Glossary glossary) { + private List getTerms(String location, DemoGlossary glossary) { try { // file로 바로 접근 할 경우, IDE에서는 접근 가능하나, jar로 패키징 후 실행 시에는 접근 불가능 // ref) https://velog.io/@haron/트러블슈팅-Spring-IDE-에서-되는데-배포하면-안-돼요 @@ -65,7 +58,7 @@ private List getTerms(String location, Glossary glossary) { } } - private static @NotNull List toTerms(List rawTerms, Glossary glossary) { + private static @NotNull List toTerms(List rawTerms, DemoGlossary glossary) { return rawTerms.stream() .map(rawTerm -> rawTerm.toTerm(glossary)) .toList(); @@ -76,8 +69,8 @@ public static class RawTerm { private String synonyms; private String meaning; - public Term toTerm(Glossary glossary) { - Term term = Term.forCreateOf(this.term, this.meaning, glossary); + public DemoTerm toTerm(DemoGlossary glossary) { + DemoTerm term = DemoTerm.forCreateOf(this.term, this.meaning, glossary); String[] synonymArray = this.synonyms.split("//n"); Arrays.stream(synonymArray) .map(String::trim) diff --git a/api/src/main/java/vook/server/api/devhelper/LocalInit.java b/api/src/main/java/vook/server/api/devhelper/LocalInit.java index dee48e2..7c6f612 100644 --- a/api/src/main/java/vook/server/api/devhelper/LocalInit.java +++ b/api/src/main/java/vook/server/api/devhelper/LocalInit.java @@ -5,7 +5,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Component; -import vook.server.api.model.MemberRepository; +import vook.server.api.model.demo.DemoGlossaryRepository; @Slf4j @Profile("local") @@ -13,12 +13,12 @@ @RequiredArgsConstructor public class LocalInit { - private final MemberRepository memberRepository; + private final DemoGlossaryRepository demoGlossaryRepository; private final InitService initService; @PostConstruct public void init() { - if (memberRepository.count() > 0) { + if (demoGlossaryRepository.count() > 0) { return; } diff --git a/api/src/main/java/vook/server/api/model/GlossaryRepository.java b/api/src/main/java/vook/server/api/model/GlossaryRepository.java deleted file mode 100644 index 0d5aaca..0000000 --- a/api/src/main/java/vook/server/api/model/GlossaryRepository.java +++ /dev/null @@ -1,9 +0,0 @@ -package vook.server.api.model; - -import org.springframework.data.jpa.repository.JpaRepository; - -import java.util.Optional; - -public interface GlossaryRepository extends JpaRepository { - Optional findByUid(String uid); -} diff --git a/api/src/main/java/vook/server/api/model/Member.java b/api/src/main/java/vook/server/api/model/Member.java deleted file mode 100644 index 2548cda..0000000 --- a/api/src/main/java/vook/server/api/model/Member.java +++ /dev/null @@ -1,28 +0,0 @@ -package vook.server.api.model; - -import jakarta.persistence.*; -import lombok.Getter; - -/** - * 회원 - */ -@Getter -@Entity -@Table(name = "member") -public class Member extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - /** - * 회원 이름 - */ - private String name; - - public static Member forCreateOf(String name) { - Member result = new Member(); - result.name = name; - return result; - } -} diff --git a/api/src/main/java/vook/server/api/model/MemberRepository.java b/api/src/main/java/vook/server/api/model/MemberRepository.java deleted file mode 100644 index e1b7308..0000000 --- a/api/src/main/java/vook/server/api/model/MemberRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package vook.server.api.model; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface MemberRepository extends JpaRepository { -} diff --git a/api/src/main/java/vook/server/api/model/Term.java b/api/src/main/java/vook/server/api/model/Term.java deleted file mode 100644 index ea551bf..0000000 --- a/api/src/main/java/vook/server/api/model/Term.java +++ /dev/null @@ -1,55 +0,0 @@ -package vook.server.api.model; - -import jakarta.persistence.*; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.List; - -/** - * 용어 - */ -@Getter -@Entity -@Table(name = "term") -public class Term extends BaseEntity { - - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - /** - * 용어 이름 - */ - @Column(length = 100, nullable = false) - private String term; - - /** - * 용어 의미 - */ - @Column(length = 2000, nullable = false) - private String meaning; - - @ManyToOne - @JoinColumn(name = "glossary_id", nullable = false) - private Glossary glossary; - - @OneToMany(mappedBy = "term", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) - private List synonyms = new ArrayList<>(); - - public static Term forCreateOf( - String term, - String meaning, - Glossary glossary - ) { - Term result = new Term(); - result.term = term; - result.meaning = meaning; - result.glossary = glossary; - return result; - } - - public void addSynonym(String synonym) { - this.synonyms.add(TermSynonym.forCreateOf(synonym, this)); - } -} diff --git a/api/src/main/java/vook/server/api/model/TermRepository.java b/api/src/main/java/vook/server/api/model/TermRepository.java deleted file mode 100644 index ca73f73..0000000 --- a/api/src/main/java/vook/server/api/model/TermRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package vook.server.api.model; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface TermRepository extends JpaRepository { -} diff --git a/api/src/main/java/vook/server/api/model/TermSynonymRepository.java b/api/src/main/java/vook/server/api/model/TermSynonymRepository.java deleted file mode 100644 index 792a437..0000000 --- a/api/src/main/java/vook/server/api/model/TermSynonymRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package vook.server.api.model; - -import org.springframework.data.jpa.repository.JpaRepository; - -public interface TermSynonymRepository extends JpaRepository { -} diff --git a/api/src/main/java/vook/server/api/model/Glossary.java b/api/src/main/java/vook/server/api/model/demo/DemoGlossary.java similarity index 56% rename from api/src/main/java/vook/server/api/model/Glossary.java rename to api/src/main/java/vook/server/api/model/demo/DemoGlossary.java index 6c28e0a..a82daf0 100644 --- a/api/src/main/java/vook/server/api/model/Glossary.java +++ b/api/src/main/java/vook/server/api/model/demo/DemoGlossary.java @@ -1,17 +1,18 @@ -package vook.server.api.model; +package vook.server.api.model.demo; import jakarta.persistence.*; import lombok.Getter; +import vook.server.api.model.BaseEntity; import java.util.UUID; /** - * 용어집 + * 데모 용어집 */ @Getter @Entity -@Table(name = "glossary") -public class Glossary extends BaseEntity { +@Table(name = "demo_glossary") +public class DemoGlossary extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -28,18 +29,12 @@ public class Glossary extends BaseEntity { */ private String name; - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "member_id", nullable = false) - private Member member; - - public static Glossary forCreateOf( - String name, - Member member + public static DemoGlossary forCreateOf( + String name ) { - Glossary result = new Glossary(); + DemoGlossary result = new DemoGlossary(); result.uid = UUID.randomUUID().toString(); result.name = name; - result.member = member; return result; } } diff --git a/api/src/main/java/vook/server/api/model/demo/DemoGlossaryRepository.java b/api/src/main/java/vook/server/api/model/demo/DemoGlossaryRepository.java new file mode 100644 index 0000000..96a223f --- /dev/null +++ b/api/src/main/java/vook/server/api/model/demo/DemoGlossaryRepository.java @@ -0,0 +1,9 @@ +package vook.server.api.model.demo; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface DemoGlossaryRepository extends JpaRepository { + Optional findByUid(String uid); +} diff --git a/api/src/main/java/vook/server/api/model/demo/DemoTerm.java b/api/src/main/java/vook/server/api/model/demo/DemoTerm.java new file mode 100644 index 0000000..2750490 --- /dev/null +++ b/api/src/main/java/vook/server/api/model/demo/DemoTerm.java @@ -0,0 +1,56 @@ +package vook.server.api.model.demo; + +import jakarta.persistence.*; +import lombok.Getter; +import vook.server.api.model.BaseEntity; + +import java.util.ArrayList; +import java.util.List; + +/** + * 데모 용어 + */ +@Getter +@Entity +@Table(name = "demo_term") +public class DemoTerm extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + /** + * 용어 이름 + */ + @Column(length = 100, nullable = false) + private String term; + + /** + * 용어 의미 + */ + @Column(length = 2000, nullable = false) + private String meaning; + + @ManyToOne + @JoinColumn(name = "demo_glossary_id", nullable = false) + private DemoGlossary demoGlossary; + + @OneToMany(mappedBy = "demoTerm", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) + private List synonyms = new ArrayList<>(); + + public static DemoTerm forCreateOf( + String term, + String meaning, + DemoGlossary demoGlossary + ) { + DemoTerm result = new DemoTerm(); + result.term = term; + result.meaning = meaning; + result.demoGlossary = demoGlossary; + return result; + } + + public void addSynonym(String synonym) { + this.synonyms.add(DemoTermSynonym.forCreateOf(synonym, this)); + } +} diff --git a/api/src/main/java/vook/server/api/model/demo/DemoTermRepository.java b/api/src/main/java/vook/server/api/model/demo/DemoTermRepository.java new file mode 100644 index 0000000..04d229a --- /dev/null +++ b/api/src/main/java/vook/server/api/model/demo/DemoTermRepository.java @@ -0,0 +1,6 @@ +package vook.server.api.model.demo; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DemoTermRepository extends JpaRepository { +} diff --git a/api/src/main/java/vook/server/api/model/TermSynonym.java b/api/src/main/java/vook/server/api/model/demo/DemoTermSynonym.java similarity index 50% rename from api/src/main/java/vook/server/api/model/TermSynonym.java rename to api/src/main/java/vook/server/api/model/demo/DemoTermSynonym.java index ab1c76b..b537a6f 100644 --- a/api/src/main/java/vook/server/api/model/TermSynonym.java +++ b/api/src/main/java/vook/server/api/model/demo/DemoTermSynonym.java @@ -1,15 +1,15 @@ -package vook.server.api.model; +package vook.server.api.model.demo; import jakarta.persistence.*; import lombok.Getter; /** - * 용어 동의어 + * 데모 용어 동의어 */ @Getter @Entity -@Table(name = "term_synonym") -public class TermSynonym { +@Table(name = "demo_term_synonym") +public class DemoTermSynonym { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @@ -22,16 +22,16 @@ public class TermSynonym { private String synonym; @ManyToOne - @JoinColumn(name = "term_id", nullable = false) - private Term term; + @JoinColumn(name = "demo_term_id", nullable = false) + private DemoTerm demoTerm; - static TermSynonym forCreateOf( + static DemoTermSynonym forCreateOf( String synonym, - Term term + DemoTerm demoTerm ) { - TermSynonym result = new TermSynonym(); + DemoTermSynonym result = new DemoTermSynonym(); result.synonym = synonym; - result.term = term; + result.demoTerm = demoTerm; return result; } } diff --git a/api/src/main/java/vook/server/api/model/demo/DemoTermSynonymRepository.java b/api/src/main/java/vook/server/api/model/demo/DemoTermSynonymRepository.java new file mode 100644 index 0000000..c8a7d95 --- /dev/null +++ b/api/src/main/java/vook/server/api/model/demo/DemoTermSynonymRepository.java @@ -0,0 +1,6 @@ +package vook.server.api.model.demo; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface DemoTermSynonymRepository extends JpaRepository { +} diff --git a/api/src/main/java/vook/server/api/outbound/search/SearchParams.java b/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchParams.java similarity index 89% rename from api/src/main/java/vook/server/api/outbound/search/SearchParams.java rename to api/src/main/java/vook/server/api/outbound/search/DemoTermSearchParams.java index 2b517fd..d9e1f30 100644 --- a/api/src/main/java/vook/server/api/outbound/search/SearchParams.java +++ b/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchParams.java @@ -4,16 +4,16 @@ import lombok.Builder; import lombok.Getter; import org.springframework.util.StringUtils; -import vook.server.api.model.Glossary; +import vook.server.api.model.demo.DemoGlossary; @Getter @Builder -public class SearchParams { +public class DemoTermSearchParams { private static final String DEFAULT_HIGHLIGHT_PRE_TAG = ""; private static final String DEFAULT_HIGHLIGHT_POST_TAG = ""; - private Glossary glossary; + private DemoGlossary demoGlossary; private String query; private boolean withFormat; private String highlightPreTag; diff --git a/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchResult.java b/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchResult.java new file mode 100644 index 0000000..73badba --- /dev/null +++ b/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchResult.java @@ -0,0 +1,23 @@ +package vook.server.api.outbound.search; + +import com.meilisearch.sdk.model.Searchable; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.HashMap; + +@Getter +public class DemoTermSearchResult { + + private String query; + private int processingTimeMs; + private ArrayList> hits; + + public static DemoTermSearchResult from(Searchable search) { + DemoTermSearchResult demoTermSearchResult = new DemoTermSearchResult(); + demoTermSearchResult.query = search.getQuery(); + demoTermSearchResult.processingTimeMs = search.getProcessingTimeMs(); + demoTermSearchResult.hits = search.getHits(); + return demoTermSearchResult; + } +} diff --git a/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchService.java b/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchService.java new file mode 100644 index 0000000..8415934 --- /dev/null +++ b/api/src/main/java/vook/server/api/outbound/search/DemoTermSearchService.java @@ -0,0 +1,99 @@ +package vook.server.api.outbound.search; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.meilisearch.sdk.Index; +import com.meilisearch.sdk.SearchRequest; +import com.meilisearch.sdk.model.Searchable; +import com.meilisearch.sdk.model.TaskInfo; +import com.meilisearch.sdk.model.TypoTolerance; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import vook.server.api.model.demo.DemoGlossary; +import vook.server.api.model.demo.DemoTerm; +import vook.server.api.model.demo.DemoTermSynonym; + +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class DemoTermSearchService extends MeilisearchService { + + private static final String INDEX_PREFIX = "demo-"; + + private final ObjectMapper objectMapper; + + public void clearAll() { + clearAll(INDEX_PREFIX); + } + + public void createGlossary(DemoGlossary demoGlossary) { + String indexUid = getIndexUid(demoGlossary); + + TaskInfo indexCreateTask = client.createIndex(indexUid, "id"); + client.waitForTask(indexCreateTask.getTaskUid()); + + // 용어, 동의어, 뜻에 대해서만 검색 + client.index(indexUid).updateSearchableAttributesSettings(new String[]{ + "term", + "synonyms", + "meaning" + }); + + // 오타 용인을 비활성화 하여도 띄어쓰기에 대해서는 검색이 됨으로 비활성화 함 + TypoTolerance typoTolerance = new TypoTolerance(); + typoTolerance.setEnabled(false); + client.index(indexUid).updateTypoToleranceSettings(typoTolerance); + } + + public void addTerms(DemoGlossary demoGlossary, List terms) { + String indexUid = getIndexUid(demoGlossary); + Index index = client.index(indexUid); + TaskInfo taskInfo = index.addDocuments(getDocuments(terms)); + client.waitForTask(taskInfo.getTaskUid()); + } + + public DemoTermSearchResult search(DemoTermSearchParams params) { + SearchRequest searchRequest = params.buildSearchRequest(); + Searchable search = this.client.getIndex(getIndexUid(params.getDemoGlossary())).search(searchRequest); + return DemoTermSearchResult.from(search); + } + + private static String getIndexUid(DemoGlossary glossary) { + return INDEX_PREFIX + glossary.getUid(); + } + + private String getDocuments(List terms) { + try { + return objectMapper.writeValueAsString(Document.from(terms)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Getter + @AllArgsConstructor + public static class Document { + private Long id; + private String term; + private String synonyms; + private String meaning; + private String createdAt; + + public static List from(List terms) { + return terms.stream() + .map(w -> new Document( + w.getId(), + w.getTerm(), + w.getSynonyms().stream().map(DemoTermSynonym::getSynonym).collect(Collectors.joining("\n")), + w.getMeaning(), + w.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) + )) + .toList(); + } + } +} diff --git a/api/src/main/java/vook/server/api/outbound/search/MeilisearchService.java b/api/src/main/java/vook/server/api/outbound/search/MeilisearchService.java index 386b8a0..dc291d1 100644 --- a/api/src/main/java/vook/server/api/outbound/search/MeilisearchService.java +++ b/api/src/main/java/vook/server/api/outbound/search/MeilisearchService.java @@ -1,122 +1,39 @@ package vook.server.api.outbound.search; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; import com.meilisearch.sdk.Client; import com.meilisearch.sdk.Config; import com.meilisearch.sdk.Index; -import com.meilisearch.sdk.SearchRequest; -import com.meilisearch.sdk.model.*; +import com.meilisearch.sdk.model.IndexesQuery; +import com.meilisearch.sdk.model.Results; import jakarta.annotation.PostConstruct; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.jetbrains.annotations.NotNull; import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Service; -import vook.server.api.model.Glossary; -import vook.server.api.model.Term; -import vook.server.api.model.TermSynonym; -import java.time.format.DateTimeFormatter; import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -@Service -@RequiredArgsConstructor -public class MeilisearchService implements SearchService, SearchClearable { - - private final ObjectMapper objectMapper; +public abstract class MeilisearchService { @Value("${service.meilisearch.host:}") - private String host; + protected String host; @Value("${service.meilisearch.apiKey:}") - private String apiKey; + protected String apiKey; - private Client client; + protected Client client; @PostConstruct public void postConstruct() { this.client = new Client(new Config(host, apiKey)); } - @Override - public void clearAll() { + protected void clearAll(String prefix) { Results indexes = client.getIndexes(new IndexesQuery() {{ setLimit(Integer.MAX_VALUE); }}); - Arrays.stream(indexes.getResults()).forEach(index -> { - client.deleteIndex(index.getUid()); - }); - } - - @Override - public void createGlossary(Glossary glossary) { - String indexUid = getIndexUid(glossary); - TaskInfo indexCreateTask = client.createIndex(indexUid, "id"); - client.waitForTask(indexCreateTask.getTaskUid()); - - // 용어, 동의어, 뜻에 대해서만 검색 - client.index(indexUid).updateSearchableAttributesSettings(new String[]{ - "term", - "synonyms", - "meaning" - }); - - // 오타 용인을 비활성화 하여도 띄어쓰기에 대해서는 검색이 됨으로 비활성화 함 - TypoTolerance typoTolerance = new TypoTolerance(); - typoTolerance.setEnabled(false); - client.index(indexUid).updateTypoToleranceSettings(typoTolerance); - } - - @Override - public void addTerms(List terms, Glossary glossary) { - Index index = client.index(getIndexUid(glossary)); - TaskInfo taskInfo = index.addDocuments(getDocuments(terms)); - client.waitForTask(taskInfo.getTaskUid()); - } - - @Override - public SearchResult search(SearchParams params) { - SearchRequest searchRequest = params.buildSearchRequest(); - Searchable search = this.client.getIndex(getIndexUid(params.getGlossary())).search(searchRequest); - return SearchResult.from(search); - } - - @NotNull - private static String getIndexUid(Glossary glossary) { - return glossary.getUid(); - } - - private String getDocuments(List terms) { - try { - return objectMapper.writeValueAsString(Document.from(terms)); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } - - @Getter - @AllArgsConstructor - public static class Document { - private Long id; - private String term; - private String synonyms; - private String meaning; - private String createdAt; - - public static List from(List terms) { - return terms.stream() - .map(w -> new Document( - w.getId(), - w.getTerm(), - w.getSynonyms().stream().map(TermSynonym::getSynonym).collect(Collectors.joining("\n")), - w.getMeaning(), - w.getCreatedAt().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME) - )) - .toList(); - } + Arrays.stream(indexes.getResults()) + .map(Index::getUid) + .filter(uid -> uid.startsWith(prefix)) + .forEach(uid -> { + client.deleteIndex(uid); + }); } } diff --git a/api/src/main/java/vook/server/api/outbound/search/SearchClearable.java b/api/src/main/java/vook/server/api/outbound/search/SearchClearable.java deleted file mode 100644 index cc17a6e..0000000 --- a/api/src/main/java/vook/server/api/outbound/search/SearchClearable.java +++ /dev/null @@ -1,5 +0,0 @@ -package vook.server.api.outbound.search; - -public interface SearchClearable { - void clearAll(); -} diff --git a/api/src/main/java/vook/server/api/outbound/search/SearchResult.java b/api/src/main/java/vook/server/api/outbound/search/SearchResult.java deleted file mode 100644 index 5ead338..0000000 --- a/api/src/main/java/vook/server/api/outbound/search/SearchResult.java +++ /dev/null @@ -1,23 +0,0 @@ -package vook.server.api.outbound.search; - -import com.meilisearch.sdk.model.Searchable; -import lombok.Getter; - -import java.util.ArrayList; -import java.util.HashMap; - -@Getter -public class SearchResult { - - private String query; - private int processingTimeMs; - private ArrayList> hits; - - public static SearchResult from(Searchable search) { - SearchResult searchResult = new SearchResult(); - searchResult.query = search.getQuery(); - searchResult.processingTimeMs = search.getProcessingTimeMs(); - searchResult.hits = search.getHits(); - return searchResult; - } -} diff --git a/api/src/main/java/vook/server/api/outbound/search/SearchService.java b/api/src/main/java/vook/server/api/outbound/search/SearchService.java deleted file mode 100644 index 826cbd6..0000000 --- a/api/src/main/java/vook/server/api/outbound/search/SearchService.java +++ /dev/null @@ -1,14 +0,0 @@ -package vook.server.api.outbound.search; - -import vook.server.api.model.Glossary; -import vook.server.api.model.Term; - -import java.util.List; - -public interface SearchService { - void createGlossary(Glossary glossary); - - void addTerms(List terms, Glossary glossary); - - SearchResult search(SearchParams params); -} diff --git a/api/src/main/java/vook/server/api/web/routes/demo/DemoWebService.java b/api/src/main/java/vook/server/api/web/routes/demo/DemoWebService.java index ed9302d..e5b0bf0 100644 --- a/api/src/main/java/vook/server/api/web/routes/demo/DemoWebService.java +++ b/api/src/main/java/vook/server/api/web/routes/demo/DemoWebService.java @@ -4,12 +4,11 @@ import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import vook.server.api.app.GlossaryService; -import vook.server.api.app.TermService; -import vook.server.api.model.Glossary; -import vook.server.api.model.Term; -import vook.server.api.outbound.search.SearchResult; -import vook.server.api.outbound.search.SearchService; +import vook.server.api.app.DemoService; +import vook.server.api.model.demo.DemoGlossary; +import vook.server.api.model.demo.DemoTerm; +import vook.server.api.outbound.search.DemoTermSearchResult; +import vook.server.api.outbound.search.DemoTermSearchService; import vook.server.api.web.routes.demo.reqres.RetrieveGlossariesResponse; import vook.server.api.web.routes.demo.reqres.RetrieveTermsResponse; import vook.server.api.web.routes.demo.reqres.SearchTermRequest; @@ -22,24 +21,23 @@ @RequiredArgsConstructor public class DemoWebService { - private final GlossaryService glossaryService; - private final TermService termService; - private final SearchService searchService; + private final DemoService demoService; + private final DemoTermSearchService searchService; public List retrieveGlossaries() { - List glossaries = glossaryService.findAll(); + List glossaries = demoService.findAllDemoGlossary(); return RetrieveGlossariesResponse.from(glossaries); } public List retrieveTerms(String glossaryUid, Pageable pageable) { - Glossary glossary = glossaryService.findByUid(glossaryUid).orElseThrow(); - List terms = termService.findAllBy(glossary, pageable); - return RetrieveTermsResponse.from(glossary, terms); + DemoGlossary glossary = demoService.findDemoGlossaryByUid(glossaryUid).orElseThrow(); + List terms = demoService.findAllDemoTermBy(glossary, pageable); + return RetrieveTermsResponse.from(terms); } public SearchTermResponse searchTerm(String glossaryUid, SearchTermRequest request) { - Glossary glossary = glossaryService.findByUid(glossaryUid).orElseThrow(); - SearchResult searchResult = searchService.search(request.toSearchParam(glossary)); + DemoGlossary glossary = demoService.findDemoGlossaryByUid(glossaryUid).orElseThrow(); + DemoTermSearchResult searchResult = searchService.search(request.toSearchParam(glossary)); return SearchTermResponse.from(searchResult); } } diff --git a/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveGlossariesResponse.java b/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveGlossariesResponse.java index 0d50c18..f71dc4c 100644 --- a/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveGlossariesResponse.java +++ b/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveGlossariesResponse.java @@ -2,7 +2,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Getter; -import vook.server.api.model.Glossary; +import vook.server.api.model.demo.DemoGlossary; import java.util.List; @@ -14,13 +14,13 @@ public class RetrieveGlossariesResponse { @Schema(description = "용어집 이름", examples = "실무") private String name; - public static List from(List glossaries) { + public static List from(List glossaries) { return glossaries.stream() .map(RetrieveGlossariesResponse::from) .toList(); } - public static RetrieveGlossariesResponse from(Glossary glossary) { + public static RetrieveGlossariesResponse from(DemoGlossary glossary) { RetrieveGlossariesResponse response = new RetrieveGlossariesResponse(); response.uid = glossary.getUid(); response.name = glossary.getName(); diff --git a/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveTermsResponse.java b/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveTermsResponse.java index 003ea3d..a4010c3 100644 --- a/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveTermsResponse.java +++ b/api/src/main/java/vook/server/api/web/routes/demo/reqres/RetrieveTermsResponse.java @@ -2,9 +2,8 @@ import com.fasterxml.jackson.annotation.JsonFormat; import lombok.Getter; -import vook.server.api.model.Glossary; -import vook.server.api.model.Term; -import vook.server.api.model.TermSynonym; +import vook.server.api.model.demo.DemoTerm; +import vook.server.api.model.demo.DemoTermSynonym; import java.time.LocalDateTime; import java.util.List; @@ -23,19 +22,19 @@ public class RetrieveTermsResponse { private String createdBy; - public static List from(Glossary glossary, List terms) { + public static List from(List terms) { return terms.stream() - .map(term -> from(glossary, term)) + .map(RetrieveTermsResponse::from) .toList(); } - public static RetrieveTermsResponse from(Glossary glossary, Term term) { + public static RetrieveTermsResponse from(DemoTerm term) { RetrieveTermsResponse response = new RetrieveTermsResponse(); response.term = term.getTerm(); - response.synonyms = term.getSynonyms().stream().map(TermSynonym::getSynonym).toList(); + response.synonyms = term.getSynonyms().stream().map(DemoTermSynonym::getSynonym).toList(); response.meaning = term.getMeaning(); response.createdAt = term.getCreatedAt(); - response.createdBy = glossary.getMember().getName(); + response.createdBy = "vook"; return response; } } diff --git a/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermRequest.java b/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermRequest.java index e45eece..120ed79 100644 --- a/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermRequest.java +++ b/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermRequest.java @@ -2,8 +2,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import vook.server.api.model.Glossary; -import vook.server.api.outbound.search.SearchParams; +import vook.server.api.model.demo.DemoGlossary; +import vook.server.api.outbound.search.DemoTermSearchParams; import static io.swagger.v3.oas.annotations.media.Schema.RequiredMode.REQUIRED; @@ -22,9 +22,9 @@ public class SearchTermRequest { @Schema(description = "하이라이트 종료 태그, 포맷 적용 여부가 true일 때만 적용 됨", defaultValue = "") private String highlightPostTag; - public SearchParams toSearchParam(Glossary glossary) { - return SearchParams.builder() - .glossary(glossary) + public DemoTermSearchParams toSearchParam(DemoGlossary glossary) { + return DemoTermSearchParams.builder() + .demoGlossary(glossary) .query(query) .withFormat(withFormat) .highlightPreTag(highlightPreTag) diff --git a/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermResponse.java b/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermResponse.java index 7a97135..dee3512 100644 --- a/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermResponse.java +++ b/api/src/main/java/vook/server/api/web/routes/demo/reqres/SearchTermResponse.java @@ -1,7 +1,7 @@ package vook.server.api.web.routes.demo.reqres; import lombok.Getter; -import vook.server.api.outbound.search.SearchResult; +import vook.server.api.outbound.search.DemoTermSearchResult; import java.util.List; import java.util.Map; @@ -12,10 +12,10 @@ public class SearchTermResponse { private String query; private List hits; - public static SearchTermResponse from(SearchResult searchResult) { - SearchTermResponse searchTermResponse = new SearchTermResponse(); - searchTermResponse.query = searchResult.getQuery(); - searchTermResponse.hits = searchResult.getHits().stream().map(document -> { + public static SearchTermResponse from(DemoTermSearchResult searchResult) { + SearchTermResponse searchResponse = new SearchTermResponse(); + searchResponse.query = searchResult.getQuery(); + searchResponse.hits = searchResult.getHits().stream().map(document -> { Object formatted = document.get("_formatted"); if (formatted instanceof Map formattedDocument) { return Document.from(formattedDocument); @@ -23,7 +23,7 @@ public static SearchTermResponse from(SearchResult searchResult) { return Document.from(document); } }).toList(); - return searchTermResponse; + return searchResponse; } @Getter