MongoDB에서 배열 요소를 제거하면서 동시에 새로운 값을 추가해야 하는 경우가 있습니다. 결론부터 말씀드리면, $addToSet 연산자와 $pull 연산자를 함께 사용하여 이 작업이 가능합니다.
테스트용 컬렉션 생성하기
먼저 예제로 사용할 문서가 포함된 컬렉션을 생성해 보겠습니다.
> db.pullAndAddToSetDemo.insertOne({StudentScores : [78, 89, 90]});{
"acknowledged" : true,
"insertedId" : ObjectId("5c9a797e15e86fd1496b38af")
}저장된 문서 확인하기
find() 메서드를 사용하여 컬렉션의 모든 문서를 조회하는 쿼리는 다음과 같습니다.
> db.pullAndAddToSetDemo.find().pretty();
위 쿼리를 실행하면 다음과 같은 결과가 출력됩니다.
{
"_id" : ObjectId("5c9a797e15e86fd1496b38af"),
"StudentScores" : [
78,
89,
90
]
}$pull과 $addToSet을 동시에 적용하기
이제 핵심 부분입니다. MongoDB에서 initializeOrderedBulkOp() 메서드를 활용하면 하나의 문서에 대해 $pull(요소 제거)과 $addToSet(중복 없이 요소 추가)을 동시에 실행할 수 있습니다.
> var addAndPull = db.pullAndAddToSetDemo.initializeOrderedBulkOp();
> addAndPull.find({ "StudentScores": 89 }).updateOne({ "$addToSet": { "StudentScores": 99 } });
> addAndPull.find({ "StudentScores": 90 }).updateOne({ "$pull": { "StudentScores": 90 } });
> addAndPull.execute();쿼리를 실행하면 다음과 같은 BulkWriteResult가 출력됩니다.
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 2,
"nModified" : 2,
"nRemoved" : 0,
"upserted" : [ ]
})결과를 살펴보면 nMatched와 nModified가 각각 2로 표시되어, 두 개의 업데이트 작업이 성공적으로 처리되었음을 알 수 있습니다.
변경 결과 검증하기
컬렉션의 문서를 다시 한번 조회하여 변경 사항이 올바르게 적용되었는지 확인해 보겠습니다.
> db.pullAndAddToSetDemo.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c9a797e15e86fd1496b38af"),
"StudentScores" : [
78,
89,
99
]
}결과 분석
출력 결과를 보면 원래 배열에 있던 값 90이 $pull 연산자에 의해 제거되었고, 새로운 값 99가 $addToSet 연산자에 의해 추가된 것을 확인할 수 있습니다. 이처럼 initializeOrderedBulkOp()를 사용하면 여러 업데이트 작업을 일괄(batch) 처리하여 배열 데이터를 유연하게 관리할 수 있습니다.