개발/DB

🎯Node.js + mongoDB:: 랜덤 추출 코드 정리

hyuunii 2022. 12. 11. 18:54

1) 랜덤 추출:: 컨트롤러나 레포단에는 별로 특별한 코드가 없다. 서비스단에서 랜덤 추출의 로직이 실행됨. 

shuffle-array라는 라이브러리 설치가 필요함(배열을 무작위로 섞어주는 역할)

※shuffle-array 설치 없이 구현하기?

아래 예제에서 shuffleArray()는 인자로 전달받은 배열의 요소를 무작위로 섞는다. 어떻게냐구?!

Math.random()는 0이상 1미만의 숫자를 리턴하고, sort()는 음수, 양수, 0의 결과 값에 따라 정렬한다.

Math.random()이 무작위로 리턴된 결과값이기 때문에 정렬 또한 무작위로 진행된다.

function shuffleArray(array) {
  array.sort(() => Math.random() - 0.5);
}

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
shuffleArray(arr);
console.log(arr);

console.log output:

[
  7,  9, 4, 8, 2,
  5, 10, 3, 6, 1
]

 

 

2) 무한스크롤:: 컨트롤러부분에서 변수 skip 지정해서 차례로 service, repo로 넘긴 후 repo에서 posts를 find 할 때 skip, limit 사용함.

- skip() 메소드: 출력할 데이터의 시작부분을 설정. value 값으로는 생략할 데이터의 갯수가 들어옴.

즉, 메소드의 인자로 들어오는 value 값 만큼 건너뛰고, value+1 부터 출력함.

e.g.) 2개의 데이터를 생략하고, 3번째 데이터부터 출력?

➜ Posts.find().skip(2)

 

- limit() 메소드: 출력하는 도큐먼트의 갯수를 제한함. 메소드의 인자 value 의 값으로 숫자가 들어가는데, 이것이 출력할 갯수임.

e.g.) Posts 컬렉션의 모든 데이터를 조회, 갯수는 3개로 제한?

 Posts.find().limit(3)

 

 

*** 아래의 무한스크롤 구현된 코드의 controller; RegExp 사용해서 req.qeury.skip 이 숫자가 아니면 0으로 변환

const skip = req.query.skip && /^\d+$/.test(req.query.skip) ? Number(req.query.skip) : 0

 

+ 위의 정규표현식 해석;

중간에 d 빠짐... /^\d+$임

정규표현식의 정규 표현식.test(주어진 문자열) 메서드는 주어진 문자열이 정규 표현식을 만족하는지 판별하고, 그 여부를 true 또는 false로 반환.

그러므로

(1)req.query로 skip이 들어오고-e.g. http://localhost:3000/posts/randomPost?skip=5-

&&

(2)그렇게 들어온것의 처음부터 끝까지가 숫자임이 만족되면

⇢true 뱉음

⇢true니까 Number(req.query.skip)이 되어서 쿼리가 숫자로 고대로 뱉어짐

(false면? 무조건 0 뱉는것)

 


코드 뜯어보기

초기 설치

$ npm install shuffle-array

 

 


<ver.무한스크롤 미적용>

controller.js

 // 전체 상품 랜덤 조회
  getAllGoods = async (req, res) => {
    try{
      const ranGoods = await this.GoodsService.findRanGoods();
      res.status(200).json({ data: ranGoods });
    }catch (error){
      res.status(404).json({error: error.message})
    }
  };

 

service.js

// 전체 상품 랜덤 추출
findRanGoods = async () => {
  const ranGoods = await this.GoodsRepository.findAllGoods();
  let result = new Array();

  for (let i = 0; i < ranGoods.length; i++){
    result.push(ranGoods[i])
  }
  shuffle_array(result);
  let slicedResult = result.slice(0, 8);
  console.log(slicedResult)

  return slicedResult
};

 

repository.js

// 상품 전체 조회
findAllGoods = async () => {
    const goods = await Goods.findAll();
    return goods;
};

 

 


<ver.무한스크롤 적용>

controller.js

//게시글 랜덤 추출
randomPost = async (req, res, next) => {
    try {
        const skip = req.query.skip && /^\d+$/.test(req.query.skip) ? Number(req.query.skip) : 0
        const randomPost = await this.postsService.getRandomPost(skip);

        res.status(200).json({data: randomPost});
    } catch (error) {
        res.status(404).json({error: error.message});
    }
}

 

service.js

//게시글 랜덤 추출
getRandomPost = async(skip) =>{
    const getRandomPost = await this.postsRepository.findAllPostsForRandomExtract(skip);
    let getRandomPostResult = new Array();

    for (let i = 0; i < getRandomPost.length; i++) {
        getRandomPostResult.push(getRandomPost[i])
    }

    shuffle_array(getRandomPostResult);
    let slicedGetRandomPostResult = getRandomPostResult.slice(0, 5);
    return slicedGetRandomPostResult;
}

 

repository.js

//게시글 랜덤 추출
findAllPostsForRandomExtract = async (skip) => {
    const findAllPostsData = await Posts.find({}, undefined, {skip: skip, limit: 5}).sort('createdAt');
    return findAllPostsData;
}