백엔드

[mongodb] 메서드 및 문법 정리

ehddkDEV 2024. 11. 15. 09:52

1.findByIdAndUpdate()

findByIdAndUpdate(
    id,                    // 첫 번째 매개변수: 업데이트할 문서의 ID
    { $set: { ... } },     // 두 번째 매개변수: 업데이트할 내용
    { new: true }          // 세 번째 매개변수: 옵션
)

 

ex> 배송지 등록

프로젝트에서 배송지 등록을 구현해야하는 부분이 있어서 서비스 부분에 

해당 메서드를 사용해야했다! 배송지를 등록하고 유저 프로필에 업데이트를 해줘야하기 때문이다!

 async createDelivery(userId: string,delivery:Omit<IDelivery,"id">):Promise<DeliveryResponseDTO>{
        console.log('userId',userId)
        try{
            //1. 유저 찾기
            const user = await this._userRepository.findById(userId);
             if (!user) {
            throw new Error('해당 유저를 찾을 수 없습니다.');
        }
            console.log('유저 찾기 :',user)
            //2. 배송지 생성하기
            const newDelivery=await this._deliveryRepository.save(
                userId,
                delivery
            )
            console.log('배송지의 userId:', newDelivery.userId);
           
            const updatedProfile = await MongooseProfile.findByIdAndUpdate(
                user.profile,
                { $set: { delivery: newDelivery} },
                { new: true }
            ).exec();
            
            console.log('Updated profile:', updatedProfile);
            return newDelivery;
        }catch(error){
            throw new Error('배송지 등록 중 오류 발생하였습니다.')
        }
    }

위 코드에서 일부분만 본다면

 const updatedProfile = await MongooseProfile.findByIdAndUpdate(
                user.profile,
                { $set: { delivery: newDelivery} },
                { new: true }
            ).exec();
            
            console.log('Updated profile:', updatedProfile);
            return newDelivery;

user.profile을 Id로 잡고 delivery에 새로운 배송지인 newDelivery를 담는것이다. 

{ new: true }를 함으로써 새로운 내용을 반환하게 된다. 

이때 ,$set을 생략해도 동일하게 작동한다! 

 

2. $push, $set

{ $push: { <field1>: <value1>, ... } }

$push 연산자는 지정된 값을 배열에 추가한다.

$set 연산자는 기존내용이 새로운 내용으로 계속 덮어씌어진다.

 

한 유저에 배송지를 계속 추가할 수 있게 스키마나 모델부분에도 배열로 설정하고 했는데도 추가가 아니라 계속 새로운 값으로 나오는거다..

알고보니 $set 연산자를 사용했고 ,  그래서 유심히 살펴보니 $push 연산자가 따로 있던 것!!

  async createDelivery(userId: string,delivery:Omit<IDelivery,"_id">):Promise<DeliveryResponseDTO>{
       //새로운 배송지
       const newDelivery=await this._deliveryRepository.save(
                userId,
                delivery
       )
            
      const updatedProfile = await MongooseProfile.findByIdAndUpdate(
        user.profile.id,
        { $push: { delivery:newDelivery} }, //delivery에 새로운배송지 등록.추가
       { new: true } // 새로운 내용을 반환
     ).exec();
 
 }

 

3. populate

테이블끼리 join을 하다보면 중첩 Populate를 하곤한다..

 

User -> profile -> delivery

예를 들어 유저 안에 프로필이 있고 그 안에 주소(배송지)부분이 있어서..서로 참조해야하는..

await MongooseUser.findById(userId)
    .populate({
        path: 'profile',
        populate: [
            {
                path: 'delivery',
                model: 'Delivery'
            },
            {
                path: '다른필드',
                model: '다른모델'
            }
        ]
    })
    .exec();

 

 

이런 식으로 path에는 실제 참조하고 있는 필드명, model에는 스키마 모델을 작성하면 된다.

참조가 잘 안되면 아예 값이 안들어오더라...