Skip to content

Commit

Permalink
Merge pull request #36 from WOK-AT/qa/place-filtering-api
Browse files Browse the repository at this point in the history
[Feature] 지하철 노선에 따라 정렬 방식 다르게 설정
  • Loading branch information
dahyunnee authored Jun 22, 2023
2 parents b3fcdb2 + c0ca822 commit 42fcbbe
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,10 @@ public class SpaceInfo extends BaseEntity {
@Schema(description = "S3 이미지 URL")
private List<String> imageURLs;

@Field("station_distance") //! [역이름: 역까지 도보거리]
@Schema(description = "서울 자치구 별 지하철역~공간 도보거리")
private Map<String, Object> walkTime;

public static SpaceInfo createSpaceInfo (PostPlaceRequest placeRequest) {
SpaceInfo spaceInfo = SpaceInfo.builder()
.space(Space.fromValue(placeRequest.getSpaceClass().toString()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public interface PlaceRepositoryCustom {

OnePlaceInfoResponse findByIdCustom(String id) throws PlaceNotFoundException ;

List<FilteringPlaceResponse> findSpaceByProperties(Space space, String area, String station,
CoordinateDTO stationCoord, FilteringPlaceRequest filteringPlaceRequest);
List<FilteringPlaceResponse> findSpaceByProperties(Space space, String area, String station,
Boolean isMainStation, CoordinateDTO stationCoord, FilteringPlaceRequest filteringPlaceRequest);

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,19 @@
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.aggregation.Aggregation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationResults;
import org.springframework.data.mongodb.core.aggregation.TypedAggregation;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.MultipartFile;

Expand Down Expand Up @@ -78,35 +80,57 @@ public SpaceInfo savePlace(List<MultipartFile> multipartFile, PostPlaceRequest p
public OnePlaceInfoResponse findByIdCustom(String id) throws PlaceNotFoundException {
SpaceInfo spaceInfo = mongoTemplate.findById(id, SpaceInfo.class);
if (spaceInfo == null) throw new PlaceNotFoundException();
LOGGER.info(spaceInfo);

OnePlaceInfoResponse placeInfoResponse = OnePlaceInfoResponse.createOnePlaceInfoResponse(spaceInfo);
return placeInfoResponse;
}

@Override
public List<FilteringPlaceResponse> findSpaceByProperties(Space space, String area, String station,
CoordinateDTO stationCoord, FilteringPlaceRequest filteringPlaceRequest) {
//* DB에서 필터링 결과 가져오기
Pageable pageable = PageRequest.of(filteringPlaceRequest.getPage(), 100,
Sort.by(Sort.Direction.ASC, "name"));
Query query = new Query().with(pageable);
Boolean isMainStation, CoordinateDTO stationCoord, FilteringPlaceRequest filteringPlaceRequest) {
List<AggregationOperation> pipeline = new ArrayList<>();

List<Criteria> criteria = new ArrayList<>();

//! 1) 카페/무료회의룸/무료공간 필터링
criteria.add(Criteria.where("space").is(space));
pipeline.add(Aggregation.match(Criteria.where("space").is(space)));

//! 2) 지역 필터링
criteria.add(Criteria.where("area").is(area));

query.addCriteria(new Criteria().andOperator(criteria.toArray(new Criteria[criteria.size()])));
List<SpaceInfo> spaceList = mongoTemplate.find(query, SpaceInfo.class);
pipeline.add(Aggregation.match(Criteria.where("area").is(area)));

//! 3-1) station이 01~09호선에 포함되는 경우 도보거리 바로 가져와서 정렬
if (isMainStation) {
pipeline.add(Aggregation.project()
.and("station_distance."+station).as("walkTimeValue") //? 도보거리 정렬
.andInclude("_id", "space_name", "space_distance", "space_headCount", "space_hashTag", "space_roadName", "space_images")
);
pipeline.add(Aggregation.sort(Sort.Direction.ASC, "walkTimeValue"));

} else { //! 3-2) 그 외의 노선인 경우 도보거리 api 요청 후 정렬
pipeline.add(Aggregation.project()
.andInclude("_id", "space_name", "space_distance", "space_headCount", "space_hashTag", "space_roadName", "space_images")
);
pipeline.add(Aggregation.sort(Sort.Direction.ASC, "space_name"));
}

//! Pagination 설정
int page = filteringPlaceRequest.getPage();
int size = 100;
pipeline.add(Aggregation.skip((long) (page * size)));
pipeline.add(Aggregation.limit(size));


//! 거리순 정렬하기
List<SpaceInfo> sortedSpace = sortSpaceByDist(spaceList, station, stationCoord);
TypedAggregation<SpaceInfo> aggregation = Aggregation.newAggregation(SpaceInfo.class, pipeline);
AggregationResults<SpaceInfo> results = mongoTemplate.aggregate(aggregation, SpaceInfo.class);
List<SpaceInfo> spaceList = results.getMappedResults();

//! 1~9 이외의 노선인 경우 따로 API 호출해서 정렬
if (!isMainStation) {
List<SpaceInfo> sortedSpace = sortSpaceByDist2(spaceList, station, stationCoord);
spaceList = sortedSpace;
}

//! DTO 넣기
List<FilteringPlaceResponse> spaceReturnList = new ArrayList<>();
for (SpaceInfo spaceInfo : sortedSpace) {
for (SpaceInfo spaceInfo : spaceList) {
FilteringPlaceResponse placeReturnDTO = new FilteringPlaceResponse();
placeReturnDTO.setId(spaceInfo.getId());
placeReturnDTO.setPlace(spaceInfo.getName());
Expand All @@ -119,45 +143,23 @@ public List<FilteringPlaceResponse> findSpaceByProperties(Space space, String ar
spaceReturnList.add(placeReturnDTO);
}


return spaceReturnList;
}

public List<SpaceInfo> sortSpaceByDist(List<SpaceInfo> spaceList, String station, CoordinateDTO stationCoord) {
Collections.sort(spaceList, new Comparator<SpaceInfo>() {
@Override
public int compare(SpaceInfo space1, SpaceInfo space2) {
//! 각 공간의 위경도 가져오기
CoordinateDTO coordinate1;
CoordinateDTO coordinate2;

try {
coordinate1 = apiLocationToCoord.getCoordByLocation(space1.getLocationRoadName());
coordinate2 = apiLocationToCoord.getCoordByLocation(space2.getLocationRoadName());
} catch (URISyntaxException e) {
throw new KakaoAPIRequestException(ErrorCode.LOCATION_TO_COORDS_FAIL);
}

LOGGER.info("{} {}", coordinate1, coordinate2);
//! 공간과 역의 도보거리
int walkTime1;
int walkTime2;

//* Tmap API 활용해 도보거리 측정
public List<SpaceInfo> sortSpaceByDist2(List<SpaceInfo> spaceList, String station, CoordinateDTO stationCoord) {
return spaceList.stream()
.sorted(Comparator.comparingInt(space -> {
try {
walkTime1 = apiGetWalkingDist.getWalkingDistance(stationCoord, station, coordinate1, space1.getName());
walkTime2 = apiGetWalkingDist.getWalkingDistance(stationCoord, station, coordinate2, space1.getName());
LOGGER.info("{} {}", walkTime1, walkTime2);
CoordinateDTO coordinate = apiLocationToCoord.getCoordByLocation(space.getLocationRoadName());
int walkTime = apiGetWalkingDist.getWalkingDistance(stationCoord, station, coordinate, space.getName());
return walkTime;
} catch (URISyntaxException | JSONException e) {
throw new TmapAPIRequestException(ErrorCode.GET_WALK_DISTANCE_FAIL);
}

int compareResult = Integer.compare(walkTime1, walkTime2);

return compareResult;
// return 1;
}
});

return spaceList;
}))
.collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -60,11 +61,21 @@ public List<FilteringPlaceResponse> filteringPlace(String placeClass, FilteringP
throw new KakaoAPIRequestException(ErrorCode.COORDS_TO_LOCATION_FAIL);
}

//! 역이 1~9호선에 속하는지 확인
Boolean isMainStation = isStationHasWalkDistance(stations);

if (area == null) return new ArrayList<>(); //! 서울특별시 아닌 경우
return placeRepository.findSpaceByProperties(space, area, filteringPlaceRequest.getStation(),
return placeRepository.findSpaceByProperties(space, area, filteringPlaceRequest.getStation(), isMainStation,
stationCoord, filteringPlaceRequest);
}

public Boolean isStationHasWalkDistance(List<Station> stations) {
String line = stations.get(0).getLine();

return Arrays.asList("01호선", "02호선", "03호선", "04호선", "05호선", "06호선", "07호선", "08호선", "09호선")
.contains(line);
}

public PostPlaceResponse postPlace(List<MultipartFile> multipartFile, PostPlaceRequest placeRequest) throws IOException {
SpaceInfo space = placeRepository.savePlace(multipartFile, placeRequest);

Expand All @@ -84,10 +95,9 @@ public OnePlaceInfoResponse findPlaceInfo(String placeId) {
public String findPlaceLocation(String placeId, int isRoadName) {
SpaceInfo foundPlace = placeRepository.findById(placeId)
.orElseThrow(PlaceNotFoundException::new);
//! 지번 주소일 경우
if(isRoadName == 0) return foundPlace.getLocationRoadName();
//! 도로명 주소일 경우
else return foundPlace.getLocationLotNumber();
String address = (isRoadName == 0) ?
foundPlace.getLocationRoadName() : foundPlace.getLocationLotNumber();
return address;
}

}

0 comments on commit 42fcbbe

Please sign in to comment.