From 329fadfaeb1139eaf06ff5d8e10d7aa9f63bdfa6 Mon Sep 17 00:00:00 2001 From: JSoi Date: Tue, 2 Aug 2022 02:32:47 +0900 Subject: [PATCH] =?UTF-8?q?#23=20[Fix]=20=EC=9C=84=EB=8F=84=20=EA=B2=BD?= =?UTF-8?q?=EB=8F=84=20=EA=B3=84=EC=82=B0=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../store/controller/StoreController.java | 2 +- .../repository/StoreQueryRepository.java | 80 +++++++++++++++---- .../baechelin/store/service/StoreService.java | 30 ++++--- 3 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/main/java/com/mpnp/baechelin/store/controller/StoreController.java b/src/main/java/com/mpnp/baechelin/store/controller/StoreController.java index 3ecdf65..1ee6c09 100644 --- a/src/main/java/com/mpnp/baechelin/store/controller/StoreController.java +++ b/src/main/java/com/mpnp/baechelin/store/controller/StoreController.java @@ -56,7 +56,7 @@ public StorePagedResponseDto getStoreInRange(@RequestParam(required = false) Big @RequestParam(required = false) List facility, @PageableDefault Pageable pageable, @AuthenticationPrincipal User user) { - return storeService.getStoreInRange(latStart, latEnd, lngStart, lngEnd, category, facility, pageable, user == null ? null : user.getUsername()); + return storeService.getStoreInTwoPointRange(latStart, latEnd, lngStart, lngEnd, category, facility, pageable, user == null ? null : user.getUsername()); } @GetMapping("/point") diff --git a/src/main/java/com/mpnp/baechelin/store/repository/StoreQueryRepository.java b/src/main/java/com/mpnp/baechelin/store/repository/StoreQueryRepository.java index 19cd395..e586468 100644 --- a/src/main/java/com/mpnp/baechelin/store/repository/StoreQueryRepository.java +++ b/src/main/java/com/mpnp/baechelin/store/repository/StoreQueryRepository.java @@ -1,21 +1,17 @@ package com.mpnp.baechelin.store.repository; -import com.mpnp.baechelin.bookmark.domain.Bookmark; -import com.mpnp.baechelin.bookmark.domain.QBookmark; import com.mpnp.baechelin.common.QueryDslSearch; import com.mpnp.baechelin.common.QuerydslLocation; import com.mpnp.baechelin.store.domain.QStore; import com.mpnp.baechelin.store.domain.Store; -import com.mpnp.baechelin.store.dto.StoreCardResponseDto; -import com.mpnp.baechelin.user.domain.QUser; -import com.mpnp.baechelin.user.domain.User; import com.querydsl.core.BooleanBuilder; +import com.querydsl.core.Tuple; +import com.querydsl.core.types.Constant; import com.querydsl.core.types.OrderSpecifier; -import com.querydsl.core.types.Projections; -import com.querydsl.core.types.dsl.BooleanExpression; +import com.querydsl.core.types.Path; +import com.querydsl.core.types.dsl.*; import com.querydsl.jpa.impl.JPAQueryFactory; import lombok.extern.slf4j.Slf4j; -import org.hibernate.criterion.Projection; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.Pageable; @@ -24,8 +20,11 @@ import javax.transaction.Transactional; import java.math.BigDecimal; +import java.math.BigInteger; import java.math.RoundingMode; +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import static com.mpnp.baechelin.common.QueryDslSearch.getSearchBooleanBuilder; import static com.mpnp.baechelin.common.QuerydslLocation.locTwoPointAndConditions; @@ -42,7 +41,7 @@ public StoreQueryRepository(JPAQueryFactory queryFactory) { this.queryFactory = queryFactory; } - public Page findBetweenOnePointOrder(BigDecimal latStart, + public Page findBetweenTwoPointOrder(BigDecimal latStart, BigDecimal latEnd, BigDecimal lngStart, BigDecimal lngEnd, @@ -54,14 +53,66 @@ public Page findBetweenOnePointOrder(BigDecimal latStart, return findBetweenOnePointOrderNullCase(builder, pageable); BigDecimal nowLat = (latStart.add(latEnd)).divide(new BigDecimal("2"), 22, RoundingMode.HALF_UP); BigDecimal nowLng = (lngStart.add(lngEnd)).divide(new BigDecimal("2"), 22, RoundingMode.HALF_UP); - List storeList = + NumberPath path = Expressions.numberPath(Double.class, "realdist"); + List tupleList = queryFactory - .selectFrom(store) + .select(store, +// ((store.latitude.subtract(nowLat)).abs().add(store.longitude.subtract(nowLng)).abs()).as(diff), + MathExpressions.acos(MathExpressions.cos(MathExpressions.radians(Expressions.constant(nowLat)))).multiply(6371) + .multiply(MathExpressions.cos(MathExpressions.radians(store.latitude))) + .multiply(MathExpressions.cos(MathExpressions.radians(store.longitude) + .subtract(MathExpressions.radians(Expressions.constant(nowLng))))) + .add(MathExpressions.sin(MathExpressions.radians(Expressions.constant(nowLat))) + .multiply(MathExpressions.sin(MathExpressions.radians(store.latitude)))).doubleValue().as(path) + ) + .from(store) .where(builder) - .orderBy(orderDistance(nowLat, nowLng)) + .orderBy(path.desc()) .limit(pageable.getPageSize()) .offset(pageable.getOffset()) .fetch(); + List storeList = tupleList.stream().map(tuple -> tuple.get(store)).collect(Collectors.toList()); + int fetchCount = queryFactory.selectFrom(store).where(builder).fetch().size(); + return new PageImpl<>(storeList, pageable, fetchCount); + } + + + public Page findBetweenOnePointOrder(BigDecimal latStart, + BigDecimal latEnd, + BigDecimal lngStart, + BigDecimal lngEnd, + BigDecimal lat, + BigDecimal lng, + String category, + List facility, + Pageable pageable) { + BooleanBuilder builder = QuerydslLocation.locAndConditions(latStart, latEnd, lngStart, lngEnd, category, facility); + if (latStart == null || lngStart == null || lngEnd == null || latEnd == null) + return findBetweenOnePointOrderNullCase(builder, pageable); + BigDecimal latH = new BigDecimal("110.852"); + BigDecimal lngH = new BigDecimal("78.847"); + NumberPath path = Expressions.numberPath(Double.class, "realdist"); + + NumberPath diff = Expressions.numberPath(BigDecimal.class, "diff"); + List tupleList = + queryFactory + .select(store, +// ((store.latitude.subtract(nowLat)).abs().add(store.longitude.subtract(nowLng)).abs()).as(diff), + MathExpressions.acos(MathExpressions.cos(MathExpressions.radians(Expressions.constant(lat)))).multiply(6371) + .multiply(MathExpressions.cos(MathExpressions.radians(store.latitude))) + .multiply(MathExpressions.cos(MathExpressions.radians(store.longitude) + .subtract(MathExpressions.radians(Expressions.constant(lng))))) + .add(MathExpressions.sin(MathExpressions.radians(Expressions.constant(lat))) + .multiply(MathExpressions.sin(MathExpressions.radians(store.latitude)))).doubleValue().as(path) + ) + .from(store) + .where(builder) +// .orderBy(diff.asc()) + .orderBy(path.asc()) + .limit(pageable.getPageSize()) + .offset(pageable.getOffset()) + .fetch(); + List storeList = tupleList.stream().map(tuple -> tuple.get(store)).collect(Collectors.toList()); int fetchCount = queryFactory.selectFrom(store).where(builder).fetch().size(); return new PageImpl<>(storeList, pageable, fetchCount); } @@ -77,10 +128,6 @@ private Page findBetweenOnePointOrderNullCase(BooleanBuilder builder, return new PageImpl<>(storeList, pageable, storeList.size()); } - private OrderSpecifier orderDistance(BigDecimal nowLat, BigDecimal nowLng) { - return QStore.store.latitude.subtract(nowLat).abs().add(QStore.store.longitude.subtract(nowLng)).abs().asc(); - } - public Page findStoreOrderByPoint(BigDecimal lat, BigDecimal lng, String category, @@ -93,7 +140,6 @@ public Page findStoreOrderByPoint(BigDecimal lat, .selectFrom(store) .where(builder) .orderBy(store.pointAvg.desc()) - .orderBy(orderDistance(lat, lng)) .limit(pageable.getPageSize()) .offset(pageable.getOffset()) .fetch(); diff --git a/src/main/java/com/mpnp/baechelin/store/service/StoreService.java b/src/main/java/com/mpnp/baechelin/store/service/StoreService.java index 2192ae5..aa37d6c 100644 --- a/src/main/java/com/mpnp/baechelin/store/service/StoreService.java +++ b/src/main/java/com/mpnp/baechelin/store/service/StoreService.java @@ -50,10 +50,19 @@ public class StoreService { * @param socialId 유저 소셜 로그인 아이디 * @return 조건을 만족하는 업장의 DTO */ - public StorePagedResponseDto getStoreInRange(BigDecimal latStart, BigDecimal latEnd, BigDecimal lngStart, BigDecimal lngEnd, String category, List facility, Pageable pageable, String socialId) { + public StorePagedResponseDto getStoreInTwoPointRange(BigDecimal latStart, BigDecimal latEnd, BigDecimal lngStart, BigDecimal lngEnd, String category, List facility, Pageable pageable, String socialId) { // public List getStoreInRange(BigDecimal latStart, BigDecimal latEnd, BigDecimal lngStart, BigDecimal lngEnd, String category, List facility, Pageable pageable, String socialId) { User targetUser = socialId == null ? null : userRepository.findBySocialId(socialId); - Page betweenLngLat = storeQueryRepository.findBetweenOnePointOrder(latStart, latEnd, lngStart, lngEnd, category, facility, pageable); + Page betweenLngLat = storeQueryRepository.findBetweenTwoPointOrder(latStart, latEnd, lngStart, lngEnd, category, facility, pageable); + // store 가져와서 dto 매핑 + return getStoreCardPagedResponseDto(targetUser, betweenLngLat); + } + + public StorePagedResponseDto getStoreInOnePointRange(BigDecimal latStart, BigDecimal latEnd, BigDecimal lngStart, BigDecimal lngEnd, BigDecimal lat, BigDecimal lng, + String category, List facility, Pageable pageable, String socialId) { +// public List getStoreInRange(BigDecimal latStart, BigDecimal latEnd, BigDecimal lngStart, BigDecimal lngEnd, String category, List facility, Pageable pageable, String socialId) { + User targetUser = socialId == null ? null : userRepository.findBySocialId(socialId); + Page betweenLngLat = storeQueryRepository.findBetweenOnePointOrder(latStart, latEnd, lngStart, lngEnd, lat, lng, category, facility, pageable); // store 가져와서 dto 매핑 return getStoreCardPagedResponseDto(targetUser, betweenLngLat); } @@ -69,9 +78,10 @@ public StorePagedResponseDto getStoreInRange(BigDecimal latStart, BigDecimal lat * @return 위도, 경도, 카테고리, 배리어 프리, 페이징을 만족하는 배리어 프리 업장 리턴 */ public StorePagedResponseDto getStoreInOnePointRange(BigDecimal lat, BigDecimal lng, String category, List facility, Pageable pageable, String socialId) { - BigDecimal[] range = QuerydslLocation.getRange(lat, lng, 10); - if (range == null) return getStoreInRange(null, null, null, null, category, facility, pageable, socialId); - return getStoreInRange(range[0], range[1], range[2], range[3], category, facility, pageable, socialId); + BigDecimal[] range = QuerydslLocation.getRange(lat, lng, 3); + if (range == null) + return getStoreInOnePointRange(null, null, null, null,lat,lng, category, facility, pageable, socialId); + return getStoreInOnePointRange(range[0], range[1], range[2], range[3],lat,lng, category, facility, pageable, socialId); } public StorePagedResponseDto getStoreInRangeMap(BigDecimal lat, BigDecimal lng, String category, List facility, Pageable pageable, String socialId) { @@ -130,6 +140,7 @@ private StorePagedResponseDto getStoreCardPagedResponseDto(User targetUser, Page /** * 업장 상세 조회 + * * @param storeId 업장 아이디 * @param socialId 유저 social 아이디 * @return 업장 상세 정보 @@ -141,7 +152,7 @@ public StoreDetailResponseDto getStore(long storeId, String socialId) { store.getStoreImageList().forEach(storeImage -> storeImageList.add(storeImage.getStoreImageUrl())); store.getReviewList().forEach(review -> review.getReviewImageList() - .forEach(reviewImage -> storeImageList.add(reviewImage.getReviewImageUrl()))); + .forEach(reviewImage -> storeImageList.add(reviewImage.getReviewImageUrl()))); User targetUser = socialId == null ? null : userRepository.findBySocialId(socialId); @@ -191,9 +202,10 @@ public Map> getSigungu(String sido) { /** * 업장 검색 - * @param sido 시/도명 - * @param sigungu 시/군/구명 - * @param keyword 검색어 + * + * @param sido 시/도명 + * @param sigungu 시/군/구명 + * @param keyword 검색어 * @param category 카테고리 * @param facility 배리어 프리 시설 * @param socialId 사용자 소셜 아이디