Repository navigation
feat: Haversine 공식 -> PostGIS 공간 함수 적용 #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
869d917
2762023
b4ab4f6
2b90a09
71171f3
2e47ce1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -6,13 +6,16 @@ | |||||
| import com.querydsl.core.BooleanBuilder; | ||||||
| import com.querydsl.core.types.dsl.Expressions; | ||||||
| import com.querydsl.core.types.dsl.NumberExpression; | ||||||
| import com.querydsl.core.types.dsl.NumberPath; | ||||||
| import com.querydsl.jpa.impl.JPAQueryFactory; | ||||||
| import com.spots.domain.program.dto.request.ProgramInfoServiceRequest; | ||||||
| import com.spots.domain.program.dto.response.ProgramInfoResponse; | ||||||
| import com.spots.domain.program.entity.QProgram; | ||||||
| import java.util.List; | ||||||
| import lombok.RequiredArgsConstructor; | ||||||
| import org.locationtech.jts.geom.Coordinate; | ||||||
| import org.locationtech.jts.geom.GeometryFactory; | ||||||
| import org.locationtech.jts.geom.Point; | ||||||
| import org.locationtech.jts.geom.PrecisionModel; | ||||||
| import org.springframework.data.domain.PageRequest; | ||||||
| import org.springframework.data.domain.Slice; | ||||||
| import org.springframework.data.domain.SliceImpl; | ||||||
|
|
@@ -34,20 +37,11 @@ public Slice<ProgramInfoResponse> searchPrograms( | |||||
| BooleanBuilder where = new BooleanBuilder(); | ||||||
|
|
||||||
| NumberExpression<Double> distance; | ||||||
| double radius = 10.0; | ||||||
|
|
||||||
| if (req.latitude() != null && req.longitude() != null) { | ||||||
| where.and(p.facility.fcltyLa.isNotNull()) | ||||||
| .and(p.facility.fcltyLo.isNotNull()); | ||||||
|
|
||||||
| distance = haversineKm( | ||||||
| req.latitude(), | ||||||
| req.longitude(), | ||||||
| p.facility.fcltyLa, | ||||||
| p.facility.fcltyLo | ||||||
| ); | ||||||
|
|
||||||
| where.and(distance.loe(radius)); | ||||||
| Point center = createPoint(req.longitude(), req.latitude()); | ||||||
| where.and(stDWithin(p, center, 10000.0)); | ||||||
| distance = stDistanceKm(p, center); | ||||||
|
Comment on lines
41
to
+44
|
||||||
| } else { | ||||||
| distance = null; | ||||||
| } | ||||||
|
Comment on lines
39
to
47
|
||||||
|
|
@@ -133,16 +127,25 @@ public Slice<ProgramInfoResponse> searchPrograms( | |||||
| return new SliceImpl<>(content, PageRequest.of(0, pageSize.intValue()), hasNext); | ||||||
| } | ||||||
|
|
||||||
| private NumberExpression<Double> haversineKm( | ||||||
| double srcLat, double srcLon, | ||||||
| NumberPath<Double> latPath, | ||||||
| NumberPath<Double> lonPath | ||||||
| ) { | ||||||
| private Point createPoint(double longitude, double latitude) { | ||||||
| return new GeometryFactory(new PrecisionModel(), 4326) | ||||||
| .createPoint(new Coordinate(longitude, latitude)); | ||||||
| } | ||||||
|
|
||||||
| private BooleanBuilder stDWithin(QProgram p, Point center, double meters) { | ||||||
| return new BooleanBuilder( | ||||||
| Expressions.booleanTemplate( | ||||||
| "function('st_dwithin', {0}, {1}, {2}) = true", | ||||||
| p.facility.location, center, meters | ||||||
| ) | ||||||
| ); | ||||||
| } | ||||||
|
|
||||||
| private NumberExpression<Double> stDistanceKm(QProgram p, Point center) { | ||||||
| return Expressions.numberTemplate( | ||||||
| Double.class, | ||||||
| "6371 * acos( cos(radians({0})) * cos(radians({1})) * cos(radians({2}) - radians({3})) " | ||||||
| + "+ sin(radians({0})) * sin(radians({1})) )", | ||||||
| srcLat, latPath, lonPath, srcLon | ||||||
| "ST_Distance({0}, {1}) / 1000.0", | ||||||
|
||||||
| "ST_Distance({0}, {1}) / 1000.0", | |
| "function('st_distance', {0}, {1}) / 1000.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spring.jpa.hibernate.ddl-auto: none설정이라 이 필드 추가만으로는 운영 DB에 컬럼이 생성되지 않습니다.facility.location(geography) 컬럼 추가/기존 데이터 backfill 및 GiST/SP-GiST 공간 인덱스 생성이 함께 반영되지 않으면 조회가 누락되거나 성능 이점이 나오기 어렵습니다. 배포 절차(마이그레이션 스크립트 등)를 PR에 포함하거나 명확히 문서화해 주세요.