MongoDB에서 _id 필드를 직접 업데이트할 수 없는 이유
MongoDB에서 _id 필드는 문서의 고유 식별자 역할을 하며, 불변(immutable) 필드로 설계되어 있습니다. 따라서 updateOne() 같은 일반적인 업데이트 연산으로는 _id 값을 직접 수정할 수 없습니다. 다만 findOne()과 save()를 조합하면 간접적으로 _id를 변경할 수 있습니다. 먼저 예제에 사용할 컬렉션을 생성해 보겠습니다.
> db.updatingIdFieldDemo.insertOne({"StudentName":"Chris"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5ce271bb36e8b255a5eee949")
}컬렉션의 모든 문서 조회하기
find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.
> db.updatingIdFieldDemo.find();
위 쿼리는 다음과 같은 결과를 출력합니다.
{ "_id" : ObjectId("5ce271bb36e8b255a5eee949"), "StudentName" : "Chris" }_id 필드를 간접적으로 변경하는 방법
다음은 _id 필드를 변경하는 과정입니다. 먼저 findOne()으로 대상 문서를 가져온 뒤 _id 값을 새로 할당하고, save()로 저장합니다. 이때 MongoDB는 기존 _id와 일치하는 문서를 찾지 못하므로 새 문서를 삽입(upsert)합니다. 마지막으로 remove()를 사용해 기존 문서를 삭제하면 _id 변경이 완료됩니다.
> var myDocument=db.updatingIdFieldDemo.findOne({StudentName:"Chris"});
> myDocument._id = 101;
101
> db.updatingIdFieldDemo.save(myDocument);
WriteResult({ "nMatched" : 0, "nUpserted" : 1, "nModified" : 0, "_id" : 101 })
> db.updatingIdFieldDemo.remove({_id:ObjectId("5ce271bb36e8b255a5eee949")});
WriteResult({ "nRemoved" : 1 })변경 결과 확인
컬렉션을 다시 조회하여 변경 사항을 확인해 보겠습니다.
> db.updatingIdFieldDemo.find();
출력 결과를 보면 _id가 101로 성공적으로 변경된 것을 확인할 수 있습니다.
{ "_id" : 101, "StudentName" : "Chris" }주의 사항
이 방식은 새 문서를 삽입한 후 기존 문서를 삭제하는 방식으로 동작합니다. 따라서 실제 운영 환경에서는 다음 사항을 반드시 고려해야 합니다.
- 다른 컬렉션이나 인덱스에서 기존 _id를 참조하고 있다면 함께 업데이트해야 합니다.
- 삽입과 삭제 사이에 장애가 발생하면 데이터 불일치가 생길 수 있으므로, 복제본 세트 환경이라면 트랜잭션 사용을 검토하는 것이 좋습니다.
- 대량의 문서를 처리할 때는 스크립트를 통해 일괄 처리하는 것이 안전합니다.