1st Project_day5_11.18

송철진·2022년 11월 18일
0

1st Project

목록 보기
3/13
post-thumbnail

상품 필터링 조회 기능을 구현하려고 한다.
where절을 만드는 함수를 어떻게 만들 수 있을까?

WHERE 절을 만드는 함수:

  • scent: 중복선택 허용 👉 OR
  • gender: 중복선택 허용 👉 OR
  • scent이면서 gender인 것: 👉 AND

소스코드

중복 허용(gender) AND 중복 허용(scent)

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})`; 
    }
}

중복 허용(gender) AND 중복 비허용(scent)

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))

1. Request URL

127.0.0.1:3000/product/all?scent[]=citrus&scent[]=fruity&gender[]=male&gender[]=female&gender[]=unisex

2. routes폴더 > index.js

routes.use("/product", productRouter.routes);

3. routes폴더 > product.router.js

routes.get("/all", productController.getAllProducts);

4. controllers폴더 > product.controller.js

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

5. services폴더 > product.service.js

함수makeWhereByGenderScent(gender, scent)를 호출해서
그 결과값을 models 단으로 넘긴다

const getProducts = async (gender, scent) => {
    let result = makeWhereByGenderScent(gender, scent);
    return await productDao.getAllProducts(result);
};

function makeWhereByGenderScent(gender, scent)

#1 객체 선언

이해를 돕기 위해 객체를 생성하여 데이터베이스 상의 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
    }

#2 gender도 scent도 undefined 일 때

URL : 127.0.0.1:3000/product/all

소스코드:

    if(!g && !sc){
      return ""; 
    }

반환되는 WHERE조건문은 없다

#3 gender가 undefined 일 때

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)

#4 scent가 undefined 일 때

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)

#5 scent와 gender가 모두 값이 있을 때

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)

6. models폴더 > product.dao.js

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문을 활용해서 작성하는 법? 아직 모르겠다;
나는 두 개를 합쳐서 작성했기에 복잡하고 길어졌다

결과(포스트맨)

시트러스이면서 남성용 향수를 조회하시오

남성용 또는 여성용 이면서 시트러스인 향수를 조회하시오

profile
검색하고 기록하며 학습하는 백엔드 개발자

0개의 댓글