์ด๋ฒ์ ์ฒ์์ผ๋ก SQL์ ์จ๋ณด๋ฉด์ ์๊ฒ ๋ ์ฌ๋ฌ ๊ฒฝํ๋ค์ ์ ๋ฆฌํด๋ณธ๋ค. ์ฌ์์์ค sql์ ๊น์ด ๊ณต๋ถํด๋ณธ ์ ์ด ์์ด์ ์ฝ๊ฐ์ ๊ผผ์์ ์ผ๋งค๊ฐ ๊ฐ๋ ์์ฌ์๋ค.
1. Select ์ ์์ ์๋ธ์ฟผ๋ฆฌ ์ฌ์ฉ
const selectItemsByCount = async (connection, limit, offset) => {
const selectItemsByCountQuery = `
SELECT (select count(*) from wish where wish.item_id = item.item_id) wish_count,
item.item_id, item.title, item.price, item.safety_pay, item.location, item.created_at, image.image_path
FROM item
INNER JOIN image
on image.item_id = item.item_id
WHERE item.status = 1
GROUP BY image.item_id
ORDER BY item.view DESC
LIMIT ?
OFFSET ?;
`;
const [itemsByCountRows] = await connection.query(selectItemsByCountQuery, [limit, offset]);
return itemsByCountRows;
};
where ์์์๋ง ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ์๋๋ฐ, select ์์์๋ ์๋ธ์ฟผ๋ฆฌ๋ฅผ ์ฌ์ฉํ ์ ์์๋ค. ์ด๊ฒ ๋ ์ฝ๋ค. ๊ทธ๋ฅ ๋๊ฐ์ด select ์ฟผ๋ฆฌ๋ฅผ ๋ง๋ค์ด์ Select ์ ์์ ์ง์ด๋ฃ๋๋ค. ํด๋น ๋ฐ์ดํฐ๋ก ๋ก์ฐ๊ฐ ์ด๋ค ์ด๋ฆ์ผ๋ก ๋ง๋ค์ด์ง์ง ์ด๋ฆ์ ์ ํด์ค๋ค. (wish_count)
2. ๋งค๋ฒ ๋ค๋ฅธ ์กฐ๊ฑด์ผ๋ก Select ํ๊ธฐ
์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ์ํ๋ค์ ๊ฐ์ ธ์ฌ ๋ ์ ์ผ ํ์ ์นดํ ๊ณ ๋ฆฌ๋ ๊ทธ๋ฅ ์นดํ ๊ณ ๋ฆฌID ๋ง๋๊ฑฐ๋ง ๊ฐ์ ธ์ค๋ฉด ๋์ง๋ง, ์์ ์นดํ ๊ณ ๋ฆฌ์ธ ๊ฒฝ์ฐ์๋ ๋ชจ๋ ํ์ ์นดํ ๊ณ ๋ฆฌ์ ์ํ๋ค์ ํ๋ฒ์ ๊ฐ์ ธ์์ผ ํ๋ค.
const readItemsByCategory = async (categoryId, limit, offset) => {
const connection = await pool.getConnection(async (conn) => conn);
const searchCategoryIdArray = [];
//์นดํ
๊ณ ๋ฆฌ๊ฐ ์์ ์นดํ
๊ณ ๋ฆฌ๋ฉด ํ์ ์นดํ
๊ณ ๋ฆฌ๋ค id ์ ๋ถ ๊ฐ์ ธ์ค๊ธฐ
const isParent = await itemDao.parentCategoryCheck(connection, categoryId);
if (isParent.length < 1) {
return errResponse(baseResponse.WRONG_CATEGORY_ID);
}
if (!isParent[0].parent_id) {
const childCategoryIdRow = await itemDao.selectChildCategoryId(connection, categoryId);
childCategoryIdRow.forEach((v) => {
searchCategoryIdArray.push(v.category_id);
});
console.log(searchCategoryIdArray);
} else {
searchCategoryIdArray.push(categoryId);
}
const ItemsByCategoryRow = await itemDao.selectItemsByCategory(connection, searchCategoryIdArray, limit, offset);
connection.release();
return response(baseResponse.SUCCESS, ItemsByCategoryRow);
};
provider.js์ ์ฝ๋. ์์ฒญ์์ ๋ฐ์ ์นดํ ๊ณ ๋ฆฌ๊ฐ ์์ ์นดํ ๊ณ ๋ฆฌ๋ฉด ํ์ ์นดํ ๊ณ ๋ฆฌ์ id๋ค์ ๊ฐ์ ธ์์ ๋ฐฐ์ด์ ๋ฃ์๋ค.
const selectItemsByCategory = async (connection, categoryIdArray, limit, offset) => {
const array = categoryIdArray.join(',');
const selectItemsByCategoryQuery = `
SELECT item.item_id, item.title, item.price, item.safety_pay, item.location, item.created_at, image.image_path, (select count(*) from wish where wish.item_id = item.item_id) wish_count
FROM item
INNER JOIN image
on image.item_id = item.item_id
WHERE category_id IN (${array}) AND item.status = 1 AND item.sale = "Sale"
GROUP BY image.item_id
ORDER BY item.view DESC
LIMIT ?
OFFSET ?;
`;
const [itemsByCategoryRows] = await connection.query(selectItemsByCategoryQuery, [limit, offset]);
return itemsByCategoryRows;
};
๊ทธ ๋ค์์ ๋ฐฐ์ด์ ','๋ก join ํด์ WHERE IN ์ ๋ฃ์ด์ฃผ์๋ค. category_id์์ (?,?,?,?..)๊ฐ ํฌํจ๋ ์ํ๋ค๋ง ๊ฐ์ ธ์จ๋ค.
3. GROUP_CONCAT
const selectReviews = async (connection, userId, limit, offset) => {
const selectReviewsQuery = `
SELECT , GROUP_CONCAT(review_image.image_path) as review_image, review.review_id, review.rank, review.content, user.user_id, user.shop_name, user.image as user_image, deal.item_id, review.created_at
FROM review
INNER JOIN deal
ON deal.deal_id = review.deal_id
INNER JOIN user
ON user.user_id = deal.buyer_id
LEFT JOIN review_image
ON review_image.review_id = review.review_id
WHERE deal.seller_id = ? AND review.status = 1
LIMIT ?
OFFSET ?;
`;
const [selectReviewsRows] = await connection.query(selectReviewsQuery, [userId, limit, offset]);
return selectReviewsRows;
};
GROUP_CONCAT์ ์ฌ์ฉํ๋ฉด ๊ฐ์ด ์ฌ๋ฌ๊ฐ ๋์ค๋ ๊ฒ๋ค์ ์ฝค๋ง(,)๋ก ๋ฌถ์ด์ ํ๋์ ๋ฌธ์์ด๋ก ๋ฐ์์ฌ ์ ์๋ค.
4. ํด๋น ๋ฌธ์์ด์ ํฌํจํ ๊ฐ ์ฐพ๊ธฐ
์ํ ๊ฒ์์ ์ํ ๋ถ๋ถ์ด๋ค. ๊ฒ์์ด ์๋์์ฑ์ ์ํด ์ฐ๋๋ฐ ์ค์ ์ดํ์์ ์ฐ๋ ๊ฒ ๋งํผ ์ ๊ตํ๊ฒ๋ ๋ชปํ๊ณ .. ๋์ ๋น์ทํ๊ฒ๋ผ๋ ๊ตฌํํด๋ณด์๋ค. ์ธํ์ ๊ฐ์ด ๋ฐ๋ ๋๋ง๋ค ๋งค๋ฒ api์์ฒญ์ ๋ณด๋ด์ ์ฌ์ฉํ๋๋ก ๋ง๋ค์๋ค.
const retrieveItemList = async (searchFor) => {
const connection = await pool.getConnection(async (conn) => conn);
const searchParamsList = searchFor.split(' ');
let searchParamsString = searchParamsList[0];
searchParamsList.forEach((v, i) => {
if (i == 0) return;
searchParamsString = searchParamsString + '|' + v;
});
const selectItemListRow = await itemDao.selectItemListPre(connection, searchParamsString); //๋ฐฐ์ด๋ก ๊ฒ์ํ๋๊ฑฐ ์ถ๊ฐํ๊ธฐ
console.log(selectItemListRow);
connection.release();
return selectItemListRow;
};
๋จผ์ provider ์ฝ๋. '์์ดํ ํ๋ก'๋ก ๊ฒ์์ด๊ฐ ๋ค์ด์ค๋ฉด '์์ดํ'๊ณผ 'ํ๋ก'๊ฐ ํฌํจ๋ ๊ฐ์ผ๋ก select ํ๋ค. ์ ๊ทํํ์์ ์ด์ฉํด์ ๊ฒ์ํ ๊ฑฐ๊ธฐ ๋๋ฌธ์ '์์ดํ|ํ๋ก'์ ํํ๋ก ๋ฌธ์์ด์ ๋ง๋ค์ด์ dao ํจ์๋ก ๋๊ฒจ์ค๋ค.
const selectItemListPre = async (connection, searchParams) => {
const selectItemListPreQuery = `
SELECT item_id, title
FROM item
WHERE item.title REGEXP ? AND item.status = 1
LIMIT 20;
`;
const [selectItemListPreRows] = await connection.query(selectItemListPreQuery, searchParams);
return selectItemListPreRows;
};
SELECT์ WHERE ์ ์์ ์ ๊ทํํ์์ ์ฌ์ฉํ ์ ์๋ค. REGEXP ์์ดํ|ํ๋ก ๋ก ๋ค์ด๊ฐ๋ฉด '์์ดํ' ๋๋ 'ํ๋ก'๊ฐ ํฌํจ๋ ๊ฐ๋ค์ ๊ฐ์ ธ์จ๋ค.