회사에서 기존 서비스 기능들을 기능 개선을 하고 있다.
mongoDB를 사용하는데 단점이…. join이 안된다…. ㅠㅠ
예를 들어 a class가 있는데 이 class에서 하나의 필드가 포인터로 b class의 기본키나 다른 키를 가리키고 있다고 하면
mysql이나 다른 곳에는 join기능이 있어 한번 쿼리로 b class의 객체까지 담아서 가져올 수 있지만 mongoDB에서는 그게 안된다…
그렇다면 어떻게 해야 할까?
어쩔 수 없다! 쿼리를 두 번해서 join을 직접 코드로 넣어줘야 한다!
두 번 쿼리 하는 거는 Promise chaining을 해서 비동기로 가져오면 된다.(이 것도 나중에 시간이 되면 정리해야겠다.)
ex)
aList = [
{
_id: "dasdas",
name: "name$asldasd", ->b class의 _id를 가르키는 포인터
startDate: "200606"
}
...
];
bList = [
{
_id: "asldasd",
phone : "010-0000-0000"
}
...
];
두 번 쿼리 한 결과가 aList와 bList의 배열 안에 이뤄져있다고 하자.(네이밍이 아주아주 중요하지만 여기서는 간단하게 설명하기 위해 대충 지었습니다.)
aList.forEach(a => {
a.name = a.name.split("$")[1];
bList.forEach(b => {
if (a.name == b._id) {
a.name = b;
}
});
});
이런 식으로 join을 할 수 있다. a의 name 필드의 값이 b의 기본키를 포인터로 가리키고 있을 때 포인터를 split 해서 문자열에서 지우고, bList를 forEach문을 돌려 선택 삽입을 하였다. 이때 시간 복잡도는 n^2이 된다.
하지만 이것을 2n으로 줄일 수 있다!
bList의 name값으로 mapping을 해줘서 key값으로 만든 다음 배열에서찾아갈 수 있도록 만 들으면된다.
let list = {};
for (let b of bList) {
list[b._id] = b;
}
aList.forEach(a => {
if (a.name.split("$")[1] in list) {
a.name = list[a.name.split("$")[1]];
}
});
이런 식으로 구현하면 된다. 여기서는 bList를 mapping 해주는 for문의 시간 복잡도 n과 aList안에 넣어주는 n을 해서 시간 복잡도를 2n으로 줄일 수 있다.
최종적으로 결과는
이런 식으로 aList의 name field안에 bList가 잘 들어간 것을 볼 수가 있다.(join 기능) 비록 Duration의 차이는별로 없겠지만이것이 하나하나쌓이다 보면 몇 초 차이가 나기 때문에 항상 내가 작성한 코드에 의구심을 들고 더 효율적인 방법을 찾아야 한다고 생각한다.
'혼자 공부하는 것들 > javascript' 카테고리의 다른 글
[JS] async와 await (0) | 2021.09.11 |
---|---|
[JS] ES6 화살표 함수와 기본 함수의 차이점을 알아보자 (0) | 2021.08.30 |
[JS] 구조분해할당 (0) | 2021.05.01 |
[JS] promise 비동기처리 (0) | 2021.04.26 |
댓글