TypeError: Converting circular structure to JSON
--> starting at object with constructor 'MongoClient' | property 's' -> object with constructor 'Object' | property 'sessionPool' -> object with constructor 'ServerSessionPool' --- property 'client' closes the circle
이는 순환참조로 인해 생기는 오류라고 한다. 찾아보니까 보통 JSON.stringify를 사용할 때 오류가 나던데 객체를 문자열로 바꾸는 과정에서 생긴다고 한다.
try {
const reviews = await Review.find({ isbn: req.body.isbn })
if (reviews.length === 0) {
res.status(404).json({
findBookReview: false,
message: 'No review corresponding to this isbn' });
}
const userIds = reviews.map(review => review.userId)
const users = await User.find({ _id: userIds })
const result = reviews.map(review => {
const user = users.find(user => user._id.toString() === review.userId.toString());
const login_user_reviews = Review.find({ userId: review.userId }).count()
console.log('login_user_reviews: ', login_user_reviews)
console.log("user: ", user._id)
return {
userId: review.userId,
isbn: review.isbn,
content: review.content ? review.content : null,
startDate: review.startDate,
createDate: review.createDate,
evaluation: review.evaluation,
profileImage: user.profileImage ? user.profileImage : null,
finRead: login_user_reviews
};
})
console.log('result: ', result)
res.status(200).json(result)
} catch (err) {
console.error('Error in read book review list', err);
res.status(500).json({ findBookReview: false, err });
}
내가 썼던 코드는 이거고 login_user_reviews 여기서 난 오류였다. 이걸 콘솔에 출력해보니
아예 이런 쿼리문이 떴다. 이 객체를 출력하려고 해서 오류가 난 것 같다. 하지만 내가 원하는 결과는 이게 아니었다.
단지 아이디에 해당하는 리뷰의 개수를 얻고 싶었던 것 뿐인데.
const login_user_reviews = await Review.find({ userId: review.userId }).count()
login_user_reviews를 검색하는 라인을 userIds를 검색하는 라인 위에 올리면 잘 검색이 되는데. await가 없어서 문제인 것 같아서 다른 방법을 찾아보았다. 그랬더니 mongodb에서 aggregate라는게 있었다.
db.orders.aggregate( [
// Stage 1: Filter pizza order documents by pizza size
{
$match: { size: "medium" }
},
// Stage 2: Group remaining documents by pizza name and calculate total quantity
{
$group: { _id: "$name", totalQuantity: { $sum: "$quantity" } }
}
] )
기본 형식은 이러하다. sql이랑 비교하자면 match는 조건을 적는 where, group은 그룹으로 묶어 집계연산을하는 group by랑 비슷하다.
그래서 예시를 보자면 size가 medium인 객체들만 추린 후, id를 기준으로 group을 묶어 quantity의 합을 계산하는 것이다.
const userIdToReviewCountMap = await Review.aggregate([
{ $match: { userId: { $in: userIds } } },
{ $group: { _id: "$userId", count: { $sum: 1 } } }
]);
나는 이렇게 작성했다. 여기서 count: { $sum: 1 }은 각 문서마다 1씩을 합해 개수를 셀 수 있다.
[ { _id: 'aaa', count: 5 }, { _id: 'eee', count: 1 } ]
그래서 출력한 결과는 이러하다. 이 결과를 아래의 코드를 통해
const userIdToReviewCount = {};
userIdToReviewCountMap.forEach(item => {
userIdToReviewCount[item._id.toString()] = item.count;
});
{ aaa: 5, eee: 1 }
id를 키로 하고 리뷰 개수를 값으로 하는 객체를 만든다.
const result = reviews.map(review => {
const user = users.find(user => user._id.toString() === review.userId.toString());
const login_user_reviews = userIdToReviewCount[review.userId.toString()] || 0;
//...
그런 다음 이 코드에서 id값으로 리뷰개수를 찾고 res로 보내주면 된다!
참고 자료
https://www.fun-coding.org/post/mongodb_advanced1.html#gsc.tab=0
https://www.mongodb.com/docs/upcoming/aggregation/
'웹' 카테고리의 다른 글
[OpenAPI] 알라딘 OpenAPI 중 검색API 이용 (0) | 2023.09.19 |
---|---|
[js] 특정 문자열 위치 여러개 찾기(indexOf 활용) (0) | 2023.09.05 |
[nginx] 설정 확인 (0) | 2023.05.23 |
[nginx / 에러] Failed to start A high performance web server and a reverse proxy server. (0) | 2023.05.22 |
[mysql] mysql 워크벤치 강제종료 (0) | 2023.05.18 |
댓글