안녕하세요

MongoDB: $addToSet 중복되는 값을 배열에 추가할 때 본문

유튜브컨텐츠탐색-StelLife/MongoDB

MongoDB: $addToSet 중복되는 값을 배열에 추가할 때

sakuraop 2023. 2. 26. 19:01

배열에 중복되는 값이 존재할 경우 추가하지 않고 싶다면: $addToSet

배열에 값을 추가할 때는 $push 연산자 말고도 $addToSet을 쓸 수 있습니다.

이름에서 알 수 있듯이 $addToSet중복을 허용하지 않습니다.

 

$addToSet 연산자를 사용하여 배열에 값을 추가할 때

해당 배열에 값이 이미 존재하는 경우 아무런 동작을 하지 않고,

배열에 값이 존재하지 않으면 새로운 값이 배열에 추가됩니다.

 

다음과 같은 컬렉션이 있다고 합시다.

{ _id: 1, number: ["one", "two", "three"] }

 

$addToSet 연산자를 사용하여 "one"을 추가하려고 하면 아무런 동작을 하지 않습니다.

db.collection.updateOne( { _id: 1 }, { $addToSet: { number: "one" } } )

 

배열 안에 존재하지 않는 "four"을 추가해봅시다.

db.collection.updateOne( { _id: 1 }, { $addToSet: { number: "four" } } )

위 코드를 실행하면, number 배열에 "four"이 추가됩니다.

 

$addToSet 연산자는 중복 값을 방지하기 때문에, 배열에 중복되지 않은 값을 추가할 때 사용하면 편리하다/

 

 


 

하지만, 객체는 추가 되는걸요? _id 가 매번 새로운 객체를 생성

https://medium.com/@tayomadein/mongodbs-addtoset-operator-using-mongo-shell-and-mongoose-odm-3edebf2bfd13

 

MongoDB’s $addToSet Operator: Using Mongo Shell and Mongoose ODM

$addToSet operator is an easy to use method of adding unique values to an array in MongoDB

medium.com

 

addToSet을 이용할 때 위와 같은 배열에 단순 string을 담은 형태가 아니라,

{ number: ["one", "two", "three"] }

 


아래와 같이 객체를 추가하고 싶다면?

foundArray.addToSet(
  { number: 'one' },
  { number: 'two' },
  { number: 'three' }
);

 

처음에는 이렇게 추가가 잘 되는 듯 하다.

foundArray : [  
    { _id: randomGeneratedId, number: 'one' },
    { _id: randomGeneratedId, number: 'two' }, 
    { _id: randomGeneratedId, number: 'three' }
]


다음으로 one을 제외하고 four, five가 추가되길 기대하면서 배열을 추가해보면?

foundArray.addToSet(
  { number: 'one' },
  { number: 'four' },
  { number: 'five' }
);


one이 그대로 추가가 되어버린다.

foundArray : [  
    { _id: randomGeneratedId, number: 'one' },
    { _id: randomGeneratedId, number: 'two' }, 
    { _id: randomGeneratedId, number: 'three' },
    { _id: randomGeneratedId, number: 'one' },
    { _id: randomGeneratedId, number: 'four' }, 
    { _id: randomGeneratedId, number: 'five' }
]

one two three one two three를 추가해도 똑같이 있는 그대로 전부 추가가 되어버리는 결과가 나타날 것이다.

 

원인은 mogodb에서 자동으로 생성하는 _id 에 있다. 

 
_id: ObjectId('63fb2aa03852bcd628bf6007)
위와 같은 랜덤한 id가 생성이 되면서
새롭게 update할 요소는 중복되지 않은 새로운 요소로 처리가 되는 것이다.

해결방법

Mongoose의 schema를 _id: false 로 지정하거나 

const citiesObjSchema = new mongoose.Schema({  key: Number,  name: String,  _id: false,});

_id fileds 를 직접(중복되지 않는 값으로) 정해주면 된다. 

              $addToSet: {
                videoArray: {
                  _id: playlistItem.snippet.resourceId.videoId,
                  publishedAt: playlistItem.snippet.publishedAt,
                  title: playlistItem.snippet.title,
                  description: playlistItem.snippet.description,
                  thumbnailsUrl: playlistItem.snippet.thumbnails.high.url,
                },
              },