상품 필터링 조회 기능을 구현하려고 한다.
where절을 만드는 함수
를 어떻게 만들 수 있을까?
WHERE 절을 만드는 함수:
- scent: 중복선택 허용 👉 OR
- gender: 중복선택 허용 👉 OR
- scent이면서 gender인 것: 👉 AND
const makeWhereByGenderScent = (g, sc) => {
const genderObj = {
male : 1,
female : 2,
unisex : 3
}
const scentObj = {
"citrus" : 1,
"fruity" : 2,
"lightfloral" : 3,
"floral" : 4,
"spicy" : 5
}
if(!g && !sc){
return "";
}else if(!g){
let scentQuery = 'WHERE (';
for(let i=0; i<sc.length; i++){
scentQuery += `sc.id = ${scentObj[sc[i]]}`;
if(i===(sc.length-1)){
return scentQuery + ')';
}
scentQuery += ' OR ';
}
}else if(!sc){
let genderQuery = 'WHERE (';
for(let i=0; i<g.length; i++){
genderQuery += `g.id = ${genderObj[g[i]]}`;
if(i===(g.length-1)){
return genderQuery + ')';
}
genderQuery += ' OR ';
}
}else{
let scentQuery = "";
for(let i=0; i<sc.length; i++){
scentQuery += `sc.id = ${scentObj[sc[i]]}`;
if(i===(sc.length-1)){
break;
}
scentQuery += ' OR ';
}
let genderQuery = "";
for(let i=0; i<g.length; i++){
genderQuery += `g.id = ${genderObj[g[i]]}`;
if(i===(g.length-1)){
break;
}
genderQuery += ' OR ';
}
return `WHERE (${scentQuery}) AND (${genderQuery})`;
}
}
const makeWhereByGenderScent = (g, sc) => {
const genderObj = {
male : 1,
female : 2,
unisex : 3
}
const scentObj = {
"citrus" : 1,
"fruity" : 2,
"lightfloral" : 3,
"floral" : 4,
"spicy" : 5
}
if(!g && !sc){
return "";
}else if(!g){
return `WHERE sc.id = ${scentObj[sc]}`;
}else if(!sc){
const genderArr = g.split(",");
let genderQuery = 'WHERE (';
for(let i=0; i<genderArr.length; i++){
genderQuery += `g.id = ${genderObj[genderArr[i]]}`;
if(i===(genderArr.length-1)){
return genderQuery + ')';
}
genderQuery += ' OR ';
}
}else{
const genderArr = g.split(",");
let genderQuery = "";
for(let i=0; i<genderArr.length; i++){
genderQuery += `g.id = ${genderObj[genderArr[i]]}`;
if(i===(genderArr.length-1)){
break;
}
genderQuery += ' OR ';
}
return `WHERE sc.id = ${scentObj[sc]} AND (${genderQuery})`;
}
}
let g = "female,male";
let sc = "citrus";
console.log(makeWhereByGenderScent(g,sc))
127.0.0.1:3000/product/all?scent[]=citrus&scent[]=fruity&gender[]=male&gender[]=female&gender[]=unisex
routes.use("/product", productRouter.routes);
routes.get("/all", productController.getAllProducts);
URL : ?gender[]=male&gender[]=female&gender[]=unisex
👉 쿼리로 할당받은 변수 gender = ["male", "female", "unisex"];
URL : &scent[]=citrus&scent[]=fruity
👉 쿼리로 할당받은 변수 scent = ["citrus", "fruity"];
const getAllProducts = async (req, res) => {
try {
const {gender, scent} = req.query;
res.status(200).json(await productService.getProducts(gender, scent));
} catch (err) {
console.log(err);
return res.status(err.statusCode || 500).json({ message: err.message });
}
};
참고 사이트
req.params vs req.query : https://wooooooak.github.io/web/2018/11/10/req.params-vs-req.query/
Parsing array from GET parameters in node.js express :
https://windix.medium.com/parsing-array-from-get-parameters-in-node-js-express-ee03d8f2ddb1
함수makeWhereByGenderScent(gender, scent)
를 호출해서
그 결과값을 models 단으로 넘긴다
const getProducts = async (gender, scent) => {
let result = makeWhereByGenderScent(gender, scent);
return await productDao.getAllProducts(result);
};
이해를 돕기 위해 객체를 생성하여 데이터베이스 상의 id값을 매칭시켰다.
const makeWhereByGenderScent = (g, sc) => {
const genderObj = {
male : 1,
female : 2,
unisex : 3
}
const scentObj = {
"citrus" : 1,
"fruity" : 2,
"lightfloral" : 3,
"floral" : 4,
"spicy" : 5
}
URL : 127.0.0.1:3000/product/all
소스코드:
if(!g && !sc){
return "";
}
반환되는 WHERE조건문은 없다
URL : 127.0.0.1:3000/product/all?scent[]=citrus&scent[]=fruity
js 👉 scent = ["citrus", "fruity"]
객체scentObj에 키 scent[i]로 접근하여
const scentObj = {
"citrus" : 1,
"fruity" : 2,
"lightfloral" : 3,
"floral" : 4,
"spicy" : 5
}
소스코드:
else if(!g){
let scentQuery = 'WHERE (';
for(let i=0; i<sc.length; i++){
scentQuery += `sc.id = ${scentObj[sc[i]]}`;
if(i===(sc.length-1)){
return scentQuery + ')';
}
scentQuery += ' OR ';
}
}
출력 결과:
WHERE (sc.id = 1 OR sc.id = 2)
URL : 127.0.0.1:3000/product/all?gender[]=male&gender[]=female&gender[]=unisex
js 👉 gender = ["male", "female", "unisex"]
객체genderObj에 키 gender[i]로 접근한다
const genderObj = {
male : 1,
female : 2,
unisex : 3
}
소스코드:
else if(!sc){
let genderQuery = 'WHERE (';
for(let i=0; i<g.length; i++){
genderQuery += `g.id = ${genderObj[g[i]]}`;
if(i===(g.length-1)){
return genderQuery + ')';
}
genderQuery += ' OR ';
}
}
출력 결과:
WHERE (g.id = 1 OR g.id = 2 OR g.id = 3)
URL : 127.0.0.1:3000/product/all?scent[]=citrus&scent[]=fruity&gender[]=male&gender[]=female&gender[]=unisex
js
👉 gender = ["male", "female", "unisex"]
👉 scent = ["citrus", "fruity"]
객체genderObj에 키 gender[i]로 접근하고
const genderObj = {
male : 1,
female : 2,
unisex : 3
}
객체scentObj에 키 scent[i]로 접근한다
const scentObj = {
"citrus" : 1,
"fruity" : 2,
"lightfloral" : 3,
"floral" : 4,
"spicy" : 5
}
소스코드:
else{
let scentQuery = "";
for(let i=0; i<sc.length; i++){
scentQuery += `sc.id = ${scentObj[sc[i]]}`;
if(i===(sc.length-1)){
break;
}
scentQuery += ' OR ';
}
let genderQuery = "";
for(let i=0; i<g.length; i++){
genderQuery += `g.id = ${genderObj[g[i]]}`;
if(i===(g.length-1)){
break;
}
genderQuery += ' OR ';
}
return `WHERE (${scentQuery}) AND (${genderQuery})`;
}
}
출력 결과:
WHERE (g.id = 1 OR g.id = 2 OR g.id = 3) AND (sc.id = 1 OR sc.id = 2)
const getAllProducts = async (result) => {
const allProducts = await appDataSource.query(
`
SELECT
p.name_en as enName,
p.name_ko koName,
JSON_ARRAYAGG(
JSON_OBJECT(
"img", po.image_url,
"size", s.name,
"price", po.price
)
) as options,
sc.name as scent,
g.name as gender,
p.created_at
FROM products p
INNER JOIN product_options po ON p.id = product_id
INNER JOIN sizes s ON s.id = size_id
INNER JOIN genders g ON g.id = p.gender_id
INNER JOIN scents sc ON sc.id = p.scent_id
${result }
GROUP BY p.id, p.name_ko
ORDER BY created_at;
`
);
return allProducts;
};
후일담
건너건너 들은 이야기로는 멘토님 왈,Services 단:
WHERE문
을 반환하는 함수와조건문
을 반환하는 함수 2가지를 만들고
각각의 결과값을 Models 단의 파라미터로 넘기면Models 단:
쿼리문 안에${ }
로 받도록 작업하면 된다고 한다
그리고 이걸 switch문을 활용해서 작성하는 법? 아직 모르겠다;
나는 두 개를 합쳐서 작성했기에 복잡하고 길어졌다
시트러스이면서 남성용 향수를 조회하시오
남성용 또는 여성용 이면서 시트러스인 향수를 조회하시오