728x90
반응형
기존에 뜨는 맛집리스트라는 기능구현을 했다.
TypeORM으로 기능 구현했는데 그룹화하고, 평균값 구하는 등 많은 일을 하려다보니
find문을 사용한후로 다양한 로직을 구현했다.
/*
### 23.03.20
### 표정훈
### [Main] 요즘 뜨는 맛집리스트🔥
*/
async HotMyList() {
try {
// 1달 전 날짜를 구한다
const oneMonthAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
// 컬렉션과 게시물, 좋아요 정보를 가져온다
const myListSumLikes = await this.collectionItemRepository.find({
relations: {
post: {
postLikes: true,
user: true,
images: true,
},
collection: {
user: true,
},
},
where: {
// 컬렉션 타입이 myList 이면서 삭제되지 않은 것을 가져온다
collection: {
type: 'myList',
deletedAt: null,
},
post: {
// 좋아요가 삭제되지 않았고, 1달 이내에 좋아요 업데이트된 게시물만 가져온다
postLikes: {
deleted_at: null,
updated_at: MoreThan(oneMonthAgo),
},
},
},
select: {
id: true,
post: {
id: true,
images: { id: true, file_url: true },
postLikes: {
id: true,
},
user: {
id: true,
nickname: true,
},
},
collection: {
id: true,
name: true,
user: {
id: true,
nickname: true,
},
},
},
take: 2,
});
// 컬렉션별 좋아요 수를 합산하여 그룹화한다
const groupedData = myListSumLikes.reduce((groups: any, item: any) => {
const collectionId = item.collection.id;
if (!groups[collectionId]) {
groups[collectionId] = {
collection: item.collection,
user: item.collection.user,
sumLikes: 0,
};
}
groups[collectionId].sumLikes += item.post?.postLikes?.length ?? 0;
// 게시물에 포함된 이미지 URL 정보를 가져온다
const images = item.post?.images ?? [];
const fileUrls = images.map((image: any) => image.file_url);
groups[collectionId].images = fileUrls;
return groups;
}, {});
// 컬렉션별 좋아요 합산값에 따라 내림차순으로 정렬한다
const collectionSumLikes: any = Object.values(groupedData);
collectionSumLikes.sort((a: any, b: any) => b.sumLikes - a.sumLikes);
// 상위 10개 컬렉션 정보를 구성하여 반환한다
const top3Collections = collectionSumLikes
// .slice(0, 10)
.map(({ collection, user, sumLikes, images }: any) => {
return {
id: collection.id,
name: collection.name,
user: {
id: user.id,
nickname: user.nickname,
},
sumLikes,
images,
};
});
return top3Collections;
}
그런데 위의 코드는 문제가 있었다. 정보를 가져올때 이미 take로 한정지어서 가져왔기에
뒤에 코드에서 몇개를 분리하든 의미가 없던 것이었다.
결국 쿼리빌더로 작성해봤는데 코드의 양이 엄청나게 줄어들었다.
/*
### 23.03.20
### 표정훈
### [Main] 요즘 뜨는 맛집리스트🔥
*/
async HotMyList() {
try {
// 1달 전 날짜를 구한다
const oneMonthAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
// 컬렉션별로 포스트의 좋아요를 모두 합쳐서 가장 좋아요수가 많은 컬렉션 5개를 순서대로 가져온다
const top5Collections = await this.collectionItemRepository
.createQueryBuilder('collectionItem')
.leftJoinAndSelect('collectionItem.collection', 'collection')
.leftJoinAndSelect('collection.user', 'user')
.leftJoinAndSelect('collectionItem.post', 'post')
.leftJoinAndSelect('post.postLikes', 'postLikes')
.where('collection.type = :type', { type: 'myList' })
.andWhere('postLikes.updated_at > :oneMonthAgo', { oneMonthAgo })
.select([
'collection.id',
'collection.name',
'user.id',
'user.nickname',
'user.profile_image',
'COUNT(postLikes.id) as sumLikes',
])
.groupBy('collection.id')
.orderBy('sumLikes', 'DESC')
.limit(5)
.getRawMany();
// 상위 5개 컬렉션 정보를 구성하여 반환한다
const topCollections = top5Collections.map((item: any) => {
return {
id: item.collection_id,
name: item.collection_name,
user: {
id: item.user_id,
nickname: item.user_nickname,
profile_image: item.user_profile_image,
},
sumLikes: item.sumLikes,
};
});
return topCollections;
}
TypeORM으로만 작성해왔는데
TypeORM 쿼리빌더가 복잡한 로직에는 훨씬 유용한것 같다.
따로 쿼리빌더를 공부해야겠다는 생각이 들었다.
728x90
반응형
'일기 > TIL' 카테고리의 다른 글
TIL: Today I Learned 92일차 [ 최종프로젝트 22일차 ] (0) | 2023.03.29 |
---|---|
TIL: Today I Learned 91일차 [ 최종프로젝트 21일차 ] (0) | 2023.03.28 |
TIL: Today I Learned 89일차 [ 최종프로젝트 19일차 ] (0) | 2023.03.23 |
TIL: Today I Learned 88일차 [ 최종프로젝트 18일차 ] (0) | 2023.03.23 |
TIL: Today I Learned 87일차 [ 최종프로젝트 17일차 ] (0) | 2023.03.23 |