MongoDB에는 애그리게이션 프레임워크의 일부로 사용할 수 있는 $toLower 연산자가 있습니다. 하지만 이미 저장된 데이터를 직접 수정해야 할 때는 forEach 루프를 사용하여 특정 필드를 순회하면서 문서를 하나씩 업데이트하는 방식이 유용합니다.
이 글에서는 예제 컬렉션을 만든 뒤, JavaScript의 toLowerCase() 함수를 활용해 StudentName 필드의 값을 모두 소문자로 변환하는 전체 과정을 단계별로 살펴보겠습니다.
1. 샘플 컬렉션 생성하기
먼저 insertOne() 메서드를 사용해 테스트용 컬렉션에 문서를 생성합니다.
> db.toLowerDemo.insertOne({"StudentId":101,"StudentName":"John"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9b1b4515e86fd1496b38bf")
}
> db.toLowerDemo.insertOne({"StudentId":102,"StudentName":"Larry"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9b1b4b15e86fd1496b38c0")
}
> db.toLowerDemo.insertOne({"StudentId":103,"StudentName":"CHris"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9b1b5115e86fd1496b38c1")
}
> db.toLowerDemo.insertOne({"StudentId":104,"StudentName":"ROBERT"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c9b1b5a15e86fd1496b38c2")
}대소문자가 섞여 있는 이름(John, Larry, CHris, ROBERT)이 저장된 것을 볼 수 있습니다.
2. 저장된 문서 확인하기
find() 메서드에 pretty()를 함께 사용하면 컬렉션의 모든 문서를 보기 좋게 출력할 수 있습니다.
> db.toLowerDemo.find().pretty();
위 쿼리는 다음과 같은 결과를 출력합니다.
{
"_id" : ObjectId("5c9b1b4515e86fd1496b38bf"),
"StudentId" : 101,
"StudentName" : "John"
}
{
"_id" : ObjectId("5c9b1b4b15e86fd1496b38c0"),
"StudentId" : 102,
"StudentName" : "Larry"
}
{
"_id" : ObjectId("5c9b1b5115e86fd1496b38c1"),
"StudentId" : 103,
"StudentName" : "CHris"
}
{
"_id" : ObjectId("5c9b1b5a15e86fd1496b38c2"),
"StudentId" : 104,
"StudentName" : "ROBERT"
}3. forEach 루프로 소문자 변환하기
이제 find().forEach()를 사용해 각 문서를 순회하면서 StudentName 필드를 소문자로 변환한 후, save()로 다시 저장하는 쿼리를 실행합니다.
> db.toLowerDemo.find().forEach(
... function(lower) {
... lower.StudentName = lower.StudentName.toLowerCase();
... db.toLowerDemo.save(lower);
... }
... );이 스크립트는 커서가 가리키는 모든 문서에 대해 자바스크립트 함수를 실행하며, 변환된 객체를 원래 _id 그대로 저장하기 때문에 기존 문서가 덮어써지는 방식으로 업데이트됩니다.
4. 업데이트 결과 확인하기
업데이트가 정상적으로 적용되었는지 다시 한번 find() 메서드로 확인해 보겠습니다.
> db.toLowerDemo.find().pretty();
실행 결과는 다음과 같습니다.
{
"_id" : ObjectId("5c9b1b4515e86fd1496b38bf"),
"StudentId" : 101,
"StudentName" : "john"
}
{
"_id" : ObjectId("5c9b1b4b15e86fd1496b38c0"),
"StudentId" : 102,
"StudentName" : "larry"
}
{
"_id" : ObjectId("5c9b1b5115e86fd1496b38c1"),
"StudentId" : 103,
"StudentName" : "chris"
}
{
"_id" : ObjectId("5c9b1b5a15e86fd1496b38c2"),
"StudentId" : 104,
"StudentName" : "robert"
}모든 StudentName 값이 john, larry, chris, robert처럼 소문자로 변경된 것을 확인할 수 있습니다.
참고: MongoDB 4.2 이상에서는 애그리게이션 파이프라인 활용 가능
MongoDB 4.2부터는 updateMany()와 애그리게이션 파이프라인을 조합해 서버 측에서 한 번의 명령으로 처리할 수도 있습니다.
> db.toLowerDemo.updateMany(
... {},
... [ { $set: { StudentName: { $toLower: "$StudentName" } } } ]
... );이 방식은 클라이언트로 문서를 가져오지 않고 서버 내부에서 변환이 이루어지므로, 대량의 데이터를 다룰 때 성능 면에서 더 유리합니다.
정리
$toLower 연산자는 원래 애그리게이션 파이프라인에서 사용되지만, 기존 컬렉션의 데이터를 일괄 변환하려면 forEach 루프와 toLowerCase()를 조합하거나, MongoDB 4.2 이상이라면 updateMany()와 파이프라인 업데이트를 활용하는 것이 효율적입니다.