구현한 부분
- 도서 좋아요 및 좋아요 삭제 기능 추가 (테이블 추가)
- 도서 목록 조회 시 좋아요 수 & 좋아요 여부 연동
- 정리
- 도서 목록 조회
- 검색조건: 전체 / 카테고리별 (where) / 신간 (where)
- 타 테이블 참조: likes,liked (서브쿼리)
- 개별 도서 조회
- 타 테이블 참조: likes, liked (서브 쿼리)
- 타 테이블 참조: 카테고리명(left join)
- 도서 목록 조회
서브쿼리
- Join 없이 다른 테이블의 정보와 함께 SELECT
- 서브쿼리 (쿼리 안 쿼리) - 쿼리의 결과값을 바깥 쿼리에 사용
- 원리
- SELECT 컬럼명1,컬럼명2 .. FROM 테이블명
- SELECT *, ( 각 행마다 likes 테이블에 liked_book_id로 가지고 있는 행 수 ) FROM books
ex) books 정보 + 해당 book id의 좋아요 수
SELECT * , (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes
FROM Bookshop.books;
ex) 개별 도서 조회 - 좋아요수, 좋아요 여부(서브쿼리), 카테고리명(left join)
SELECT * ,
(SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
(SELECT count(*) FROM likes WHERE user_id=1 AND liked_book_id=1) AS liked
FROM Bookshop.books
LEFT JOIN category
ON books.category_id=category.category_id
WHERE books.id=1;
workbench확인
존재 여부?
다음 두가지 방법은 결과는 같다.
1. SELECT EXISTS 이용
SELECT EXISTS (SELECT * FROM likes WHERE user_id=1 AND liked_book_id=1) AS isexist
결과
2. count(*)이용
SELECT count(*) FROM likes WHERE user_id=1 AND liked_book_id=1
결과
BookController.js
const conn = require("../mariadb");
const { StatusCodes } = require("http-status-codes");
const allBooks = (req, res) => {
const { category_id, new_book, limit, current_page } = req.query;
let offset = limit * (current_page - 1);
let sql =
"SELECT *, (SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes FROM books";
let values = [];
if (category_id && new_book) {
sql +=
" WHERE category_id=? AND pub_date BETWEEN DATE_SUB(NOW(),INTERVAL 1 MONTH) AND NOW()";
values.push(category_id);
} else if (new_book) {
sql += " WHERE pub_date BETWEEN DATE_SUB(NOW(),INTERVAL 1 MONTH) AND NOW()";
} else if (category_id) {
sql += " WHERE category_id=?";
values.push(category_id);
}
sql += "LIMIT ? OFFSET ?";
values.push(parseInt(limit), parseInt(offset));
conn.query(sql, values, (err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
if (results.length > 0) {
return res.status(StatusCodes.OK).json(results);
} else {
return res.status(StatusCodes.NOT_FOUND).end();
}
});
};
//개별 도서 조회
const book = (req, res) => {
let { user_id } = req.body;
const { id: book_id } = req.params;
let sql = `SELECT * ,
(SELECT count(*) FROM likes WHERE liked_book_id=books.id) AS likes,
(SELECT count(*) FROM likes WHERE user_id=? AND liked_book_id=?) AS liked
FROM Bookshop.books
LEFT JOIN category
ON books.category_id=category.category_id
WHERE books.id=?;`;
let values = [user_id, book_id, book_id];
conn.query(sql, values, (err, results) => {
if (err) {
console.log(err);
return res.status(StatusCodes.BAD_REQUEST).end();
}
if (results.length > 0) {
return res.status(StatusCodes.OK).json(results);
} else {
return res.status(StatusCodes.NOT_FOUND).end();
}
});
};
module.exports = {
allBooks,
book,
};
id가 많아짐에 따라 어떤 id인지 알아보기 쉽게 비구조화시 명칭을 지어주었다.
const { id: book_id } = req.params;
'타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) > TIL' 카테고리의 다른 글
데브코스 9주차 Day 2,3,4 - [쇼핑몰]주문 controller, 비동기, promise (0) | 2024.01.12 |
---|---|
데브코스 9주차 Day1 - [쇼핑몰]장바구니 controller , 중복 오류, ES6 문법 (0) | 2024.01.08 |
데브코스 8주차 Day3 - 도서 기간 내 검색, 페이징 구현 (0) | 2024.01.05 |
데브코스 8주차 Day2 - FK, book/category - Controller , 데이터 join (0) | 2024.01.05 |
데브코스 8주차 day1 - http-status-code 모듈, 폴더구조, 암호화, user 컨트롤러 구현 (0) | 2024.01.05 |