728x90
반응형

컬렉션 안에 있는 맛집별로 평균 평점을 구하는 작업을 했다.

처음엔 아무 생각없이 모든 평점을 모아서 평균을 냈는데, 생각해보니

1가지 맛집에 대한 평점만 낸것이어서, 다른 맛집도 추가하여 분리해보았다.

 

맛집ID가 같은 것끼리 분리해야하니, 그룹화가 필요했고,

그룹화 이후 각 포스트 정보는 1개씩만 대표로 가져오게 했다.

 

  async getMyListDetail(collectionId: number, page: string) {
    try {
      let pageNum = Number(page) - 1;
      const myListInOnePage = 1;

      if (isNaN(pageNum) || pageNum < 0) {
        pageNum = 0;
      }

      // 컬렉션 이름과 포스트 정보 가져오기
      const myList = await this.collectionRepository.find({
        relations: {
          collectionItems: {
            post: { images: true, restaurant: true },
          },
        },
        where: {
          id: collectionId,
          // user_id: userId,
          deletedAt: null,
          type: 'myList',
        },
        select: {
          id: true,
          name: true,
          description: true,
          visibility: true,
          collectionItems: {
            id: true,
            post: {
              id: true,
              content: true,
              rating: true,
              images: true,
              restaurant: {
                id: true,
                x: true,
                y: true,
                place_name: true,
                category_group_name: true,
              },
            },
          },
        },
        skip: pageNum * myListInOnePage,
        take: myListInOnePage,
      });

      const [myListDetail] = myList.map((myList) => {
        const groupedPosts = {};
        for (const item of myList.collectionItems) {
          
          const restaurantId = item.post.restaurant.id;
          if (!groupedPosts[restaurantId]) {
            groupedPosts[restaurantId] = { posts: [], sum: 0, count: 0 };
          }
          groupedPosts[restaurantId].posts.push({
            ...item.post,
            restaurant: item.post.restaurant,
            images: item.post.images,
          });
          
          const rating = item.post.rating;
          if (typeof rating === 'number') {
            groupedPosts[restaurantId].sum += rating;
            groupedPosts[restaurantId].count++;
          }
        }

        
        const formattedPosts = [];
        for (const groupId in groupedPosts) {
          const group = groupedPosts[groupId];
          const avgRating =
            group.count > 0 ? (group.sum / group.count).toFixed(1) : null;

          if (group.posts.length > 0) {
            formattedPosts.push({
              id: group.posts[0].id,
              content: group.posts[0].content,
              rating: group.posts[0].rating,
              AvgRating: avgRating,
              images: group.posts[0].images,
              restaurant: group.posts[0].restaurant,
            });
          }
        }

        return {
          id: myList.id,
          name: myList.name,
          description: myList.description,
          visibility: myList.visibility,
          post: formattedPosts,
        };
      });

      return myListDetail;
    } catch (err) {
      console.error(err);
      throw new InternalServerErrorException(
        'Something went wrong while processing your request. Please try again later.',
      );
    }
  }
728x90
반응형

+ Recent posts