Skip to content

Commit

Permalink
Merge pull request #77 from Na-o-man/feat/#74/get-face-photoList-api
Browse files Browse the repository at this point in the history
[FEAT] 특정 공유 그룹의 특정 앨범의 사진을 조회하는 API
  • Loading branch information
bflykky authored Aug 10, 2024
2 parents 73a63c2 + b836d9e commit 1662184
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 98 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.umc.naoman.domain.photo.converter.PhotoConverter;
import com.umc.naoman.domain.photo.dto.PhotoRequest;
import com.umc.naoman.domain.photo.dto.PhotoResponse;
import com.umc.naoman.domain.photo.elasticsearch.document.PhotoEs;
import com.umc.naoman.domain.photo.elasticsearch.service.PhotoEsService;
import com.umc.naoman.domain.photo.entity.Photo;
import com.umc.naoman.domain.photo.service.PhotoService;
import com.umc.naoman.global.result.ResultResponse;
Expand Down Expand Up @@ -37,6 +39,7 @@
public class PhotoController {

private final PhotoService photoService;
private final PhotoEsService photoEsService;
private final PhotoConverter photoConverter;

@PostMapping("/preSignedUrl")
Expand All @@ -55,18 +58,36 @@ public ResultResponse<PhotoResponse.PhotoUploadInfo> uploadPhotoList(@Valid @Req
return ResultResponse.of(UPLOAD_PHOTO, photoUploadInfo);
}

@GetMapping
@Operation(summary = "특정 공유그룹의 특정 앨범 사진 조회 API", description = "특정 공유 그룹의 특정 앨범의 사진을 조회하는 API입니다.")
@Parameters(value = {
@Parameter(name = "shareGroupId", description = "조회할 공유 그룹의 아이디를 입력해주세요."),
@Parameter(name = "profileId", description = "조회할 프로필의 아이디를 입력해주세요."),
@Parameter(name = "page", description = "조회할 페이지를 입력해 주세요.(0번부터 시작)"),
@Parameter(name = "size", description = "한 페이지에 나타낼 사진 개수를 입력해주세요.")
})
public ResultResponse<PhotoResponse.PagedPhotoEsInfo> getAllPhotoListByShareGroup(@RequestParam Long shareGroupId,
@RequestParam Long profileId,
@PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC)
@Parameter(hidden = true) Pageable pageable,
@LoginMember Member member) {
Page<PhotoEs> photoEsList = photoEsService.getPhotoEsListByShareGroupIdAndFaceTag(shareGroupId, profileId, member, pageable);
return ResultResponse.of(RETRIEVE_PHOTO, photoConverter.toPagedPhotoEsInfo(photoEsList, member));
}

@GetMapping("/all")
@Operation(summary = "특정 공유그룹의 전체 사진 조회 API", description = "특정 공유 그룹의 전체 사진을 조회하는 API입니다.")
@Parameters(value = {
@Parameter(name = "shareGroupId", description = "조회할 공유 그룹의 아이디를 입력해주세요."),
@Parameter(name = "page", description = "조회할 페이지를 입력해 주세요.(0번부터 시작)"),
@Parameter(name = "size", description = "한 페이지에 나타낼 사진 개수를 입력해주세요.")
})
public ResultResponse<PhotoResponse.PagedPhotoInfo> getAllPhotoListByShareGroup(@RequestParam Long shareGroupId,
@PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC)
@Parameter(hidden = true) Pageable pageable,
@LoginMember Member member) {
Page<Photo> allPhotoListByShareGroup = photoService.getAllPhotoList(shareGroupId, member, pageable);
return ResultResponse.of(RETRIEVE_PHOTO, photoConverter.toPhotoListInfo(allPhotoListByShareGroup));
public ResultResponse<PhotoResponse.PagedPhotoEsInfo> getAllPhotoListByShareGroup(@RequestParam Long shareGroupId,
@PageableDefault(sort = "createdAt", direction = Sort.Direction.DESC)
@Parameter(hidden = true) Pageable pageable,
@LoginMember Member member) {
Page<PhotoEs> photoEsList = photoEsService.getPhotoEsListByShareGroupId(shareGroupId, member, pageable);
return ResultResponse.of(RETRIEVE_PHOTO, photoConverter.toPagedPhotoEsInfo(photoEsList, member));
}

@DeleteMapping
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package com.umc.naoman.domain.photo.converter;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.photo.dto.PhotoResponse;
import com.umc.naoman.domain.photo.elasticsearch.document.PhotoEs;
import com.umc.naoman.domain.photo.entity.Photo;
import com.umc.naoman.domain.shareGroup.entity.ShareGroup;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

Expand Down Expand Up @@ -44,32 +47,35 @@ public Photo toEntity(String photoUrl, String photoName, ShareGroup shareGroup)
.build();
}

public PhotoResponse.PagedPhotoInfo toPhotoListInfo(Page<Photo> photoList) {
List<PhotoResponse.PhotoInfo> photoInfoList = photoList.stream()
.map(this::toPhotoInfo)
public PhotoResponse.PagedPhotoEsInfo toPagedPhotoEsInfo(Page<PhotoEs> photoEsList, Member member) {
List<PhotoResponse.PhotoEsInfo> photoEsInfoList = photoEsList.stream()
.map(photoEs -> toPhotoEsInfo(photoEs, member))
.collect(Collectors.toList());

return PhotoResponse.PagedPhotoInfo.builder()
.isLast(photoList.isLast())
.isFirst(photoList.isFirst())
.totalPage(photoList.getTotalPages())
.totalElements(photoList.getTotalElements())
.photoInfoList(photoInfoList)
return PhotoResponse.PagedPhotoEsInfo.builder()
.isLast(photoEsList.isLast())
.isFirst(photoEsList.isFirst())
.totalPages(photoEsList.getTotalPages())
.totalElements(photoEsList.getTotalElements())
.photoEsInfoList(photoEsInfoList)
.build();
}

public PhotoResponse.PhotoInfo toPhotoInfo(Photo photo) {
String rawUrl = photo.getUrl();
public PhotoResponse.PhotoEsInfo toPhotoEsInfo(PhotoEs photoEs, Member member) {
String rawUrl = photoEs.getUrl();
Boolean isDownload = !photoEs.getDownloadTag().isEmpty() && photoEs.getDownloadTag().contains(member.getId());

return PhotoResponse.PhotoInfo.builder()
.photoId(photo.getId())
return PhotoResponse.PhotoEsInfo.builder()
.photoId(photoEs.getRdsId())
.rawPhotoUrl(rawUrl)
.w200PhotoUrl(createResizedPhotoUrl(rawUrl, W200_PATH_PREFIX))
.w400PhotoUrl(createResizedPhotoUrl(rawUrl, W400_PATH_PREFIX))
.createdAt(photo.getCreatedAt())
.isDownload(isDownload)
.createdAt(LocalDateTime.parse(photoEs.getCreatedAt()))
.build();
}


private String createResizedPhotoUrl(String photoUrl, String size) {
String resizedUrl = getResizedUrl(photoUrl, size);
return convertExtension(resizedUrl);
Expand Down
19 changes: 10 additions & 9 deletions src/main/java/com/umc/naoman/domain/photo/dto/PhotoResponse.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package com.umc.naoman.domain.photo.dto;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.HttpHeaders;

import java.time.LocalDateTime;
import java.util.List;
Expand Down Expand Up @@ -43,23 +42,25 @@ public static class PhotoUploadInfo {
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class PagedPhotoInfo {
private List<PhotoInfo> photoInfoList;
Integer totalPage;
Long totalElements;
Boolean isFirst;
Boolean isLast;
public static class PagedPhotoEsInfo {
private List<PhotoEsInfo> photoEsInfoList;
private Integer totalPages;
private Long totalElements;
private Boolean isFirst;
private Boolean isLast;
}

@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public static class PhotoInfo {
public static class PhotoEsInfo {
private Long photoId;
private String rawPhotoUrl;
private String w200PhotoUrl;
private String w400PhotoUrl;
private Boolean isDownload;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.umc.naoman.domain.photo.elasticsearch.document;

import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.time.LocalDateTime;
import java.util.List;

@Getter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public void savePhotoBulk(List<Photo> photoList) {
.build())
.toList();
BulkRequest.Builder bulkBuilder = new BulkRequest.Builder();
for(PhotoEs photoEs :photoEsList){
bulkBuilder.operations(op ->op
for (PhotoEs photoEs : photoEsList) {
bulkBuilder.operations(op -> op
.index(idx -> idx
.index("photos_es")
.routing(photoEs.getShareGroupId().toString())
Expand All @@ -62,17 +62,17 @@ public Page<PhotoEs> findPhotoEsByShareGroupId(Long shareGroupId, Pageable pagea
SearchResponse<PhotoEs> response = null;

pageable.getPageNumber();
try{
response = elasticsearchClient.search(s->s
try {
response = elasticsearchClient.search(s -> s
.index("photos_es")
.routing(shareGroupId.toString())
.from(getFrom(pageable))
.size(pageable.getPageSize())
.sort(sort -> sort
.field(f -> f
.field("createdAt")))
.query(q->q
.term(t->t
.field(f -> f
.field("createdAt")))
.query(q -> q
.term(t -> t
.field("shareGroupId")
.value(shareGroupId)
)
Expand All @@ -86,27 +86,27 @@ public Page<PhotoEs> findPhotoEsByShareGroupId(Long shareGroupId, Pageable pagea
}

//특정 공유 그룹의 얼굴이 태그된 사진 검색
public Page<PhotoEs> findPhotoEsByShareGroupIdAndFaceTag(Long shareGroupId,Long faceTag, Pageable pageable) {
public Page<PhotoEs> findPhotoEsByShareGroupIdAndFaceTag(Long shareGroupId, Long faceTag, Pageable pageable) {
SearchResponse<PhotoEs> response = null;
try{
response = elasticsearchClient.search(s->s
try {
response = elasticsearchClient.search(s -> s
.index("photos_es")
.routing(shareGroupId.toString())
.from(getFrom(pageable))
.size(pageable.getPageSize())
.sort(sort -> sort
.field(f -> f
.field("createdAt")))
.query(q->q
.bool(b->b
.must(m->m
.term(t->t
.query(q -> q
.bool(b -> b
.must(m -> m
.term(t -> t
.field("shareGroupId")
.value(shareGroupId)
)
)
.must(m->m
.term(t->t
.must(m -> m
.term(t -> t
.field("faceTag")
.value(faceTag)
)
Expand All @@ -123,18 +123,18 @@ public Page<PhotoEs> findPhotoEsByShareGroupIdAndFaceTag(Long shareGroupId,Long
}

//특정 공유 그룹의 얼굴이 태그되지 않은 사진 검색
public Page<PhotoEs> findPhotoEsByShareGroupIdAndNotFaceTag(Long shareGroupId, Pageable pageable){
public Page<PhotoEs> findPhotoEsByShareGroupIdAndNotFaceTag(Long shareGroupId, Pageable pageable) {
SearchResponse<PhotoEs> response = null;
try{
response = elasticsearchClient.search(s->s
try {
response = elasticsearchClient.search(s -> s
.index("photos_es")
.routing(shareGroupId.toString())
.from(getFrom(pageable))
.size(pageable.getPageSize())
.sort(sort -> sort
.field(f -> f
.field("createdAt")))
.query(q->q
.query(q -> q
.bool(b -> b
.must(m -> m
.term(t -> t
Expand All @@ -151,24 +151,24 @@ public Page<PhotoEs> findPhotoEsByShareGroupIdAndNotFaceTag(Long shareGroupId, P
),
PhotoEs.class
);
}catch (IOException e){
} catch (IOException e) {
throw new BusinessException(ElasticsearchErrorCode.ELASTICSEARCH_IOEXCEPTION, e);
}

return toPagePhotoEs(response.hits().hits(), pageable);
}

String esTimeFormat(LocalDateTime localDateTime){
String esTimeFormat(LocalDateTime localDateTime) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return localDateTime.format(dateTimeFormatter);
}

private Page<PhotoEs> toPagePhotoEs(List<Hit<PhotoEs>> hits, Pageable pageable){
private Page<PhotoEs> toPagePhotoEs(List<Hit<PhotoEs>> hits, Pageable pageable) {
List<PhotoEs> photoEsList = hits.stream().map(Hit::source).collect(Collectors.toList());
return new PageImpl<>(photoEsList, pageable, hits.size());
}

private int getFrom(Pageable pageable){
private int getFrom(Pageable pageable) {
return pageable.getPageNumber() * pageable.getPageSize();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.umc.naoman.domain.photo.elasticsearch.service;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.photo.elasticsearch.document.PhotoEs;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

public interface PhotoEsService {
Page<PhotoEs> getPhotoEsListByShareGroupId(Long shareGroupId, Member member, Pageable pageable);
Page<PhotoEs> getPhotoEsListByShareGroupIdAndFaceTag(Long shareGroupId, Long profileId, Member member, Pageable pageable);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.umc.naoman.domain.photo.elasticsearch.service;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.photo.elasticsearch.document.PhotoEs;
import com.umc.naoman.domain.photo.elasticsearch.repository.PhotoEsClientRepository;
import com.umc.naoman.domain.shareGroup.service.ShareGroupService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class PhotoEsServiceImpl implements PhotoEsService {

private final PhotoEsClientRepository photoEsClientRepository;
private final ShareGroupService shareGroupService;

@Override
@Transactional(readOnly = true)
public Page<PhotoEs> getPhotoEsListByShareGroupIdAndFaceTag(Long shareGroupId, Long profileId, Member member, Pageable pageable) {
validateShareGroupAndProfile(shareGroupId, member);
Long memberId = shareGroupService.findProfile(profileId).getMember().getId();
return photoEsClientRepository.findPhotoEsByShareGroupIdAndFaceTag(shareGroupId, memberId, pageable);
}

@Override
@Transactional(readOnly = true)
public Page<PhotoEs> getPhotoEsListByShareGroupId(Long shareGroupId, Member member, Pageable pageable) {
validateShareGroupAndProfile(shareGroupId, member);
return photoEsClientRepository.findPhotoEsByShareGroupId(shareGroupId, pageable);
}

private void validateShareGroupAndProfile(Long shareGroupId, Member member) {
// 해당 공유 그룹이 존재하는지 확인
shareGroupService.findShareGroup(shareGroupId);
// 멤버가 해당 공유 그룹에 속해있는지 확인
shareGroupService.findProfile(shareGroupId, member.getId());
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package com.umc.naoman.domain.photo.entity;

import com.umc.naoman.domain.member.entity.Member;
import com.umc.naoman.domain.shareGroup.entity.ShareGroup;
import com.umc.naoman.global.entity.BaseTimeEntity;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
Expand Down
Loading

0 comments on commit 1662184

Please sign in to comment.