MongoDB 대소문자 구분 없이 검색하기
데이터베이스 작업을 하다 보면 저장된 값의 대소문자와 관계없이 특정 데이터를 조회해야 하는 경우가 자주 발생합니다. 예를 들어 이메일 주소가 JOHN@GMAIL.COM으로 저장되어 있어도 사용자가 john@gmail.com으로 검색하면 결과를 찾아야 하죠. MongoDB에서는 정규 표현식(regular expression)에 i 옵션을 활용하면 이러한 대소문자를 구분하지 않는(case-insensitive) 검색을 손쉽게 구현할 수 있습니다.
이번 글에서는 실제 예제를 통해 컬렉션 생성부터 대소문자 무시 검색 쿼리까지 단계별로 살펴보겠습니다.
1. 문서가 포함된 컬렉션 생성하기
먼저 insertOne() 메서드를 사용하여 샘플 문서들을 담은 컬렉션을 만들어 보겠습니다. 의도적으로 이메일 주소를 대문자, 소문자가 섞인 다양한 형태로 저장했습니다.
> db.demo186.insertOne({"UserEmailId":"JOHN@GMAIL.COM","UserName":"John"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399d769e4f06af55199808")
}
> db.demo186.insertOne({"UserEmailId":"chris@gmail.com","UserName":"chris"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399d879e4f06af55199809")
}
> db.demo186.insertOne({"UserEmailId":"DAVID@GMAIL.COM","UserName":"David"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5e399d979e4f06af5519980a")
}2. find()로 전체 문서 확인하기
find() 메서드를 호출하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.
> db.demo186.find();
위 명령을 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
{ "_id" : ObjectId("5e399d769e4f06af55199808"), "UserEmailId" : "JOHN@GMAIL.COM", "UserName" : "John" }
{ "_id" : ObjectId("5e399d879e4f06af55199809"), "UserEmailId" : "chris@gmail.com", "UserName" : "chris" }
{ "_id" : ObjectId("5e399d979e4f06af5519980a"), "UserEmailId" : "DAVID@GMAIL.COM", "UserName" : "David" }출력 결과를 보면 세 개의 문서가 각각 다른 대소문자 조합으로 저장되어 있는 것을 확인할 수 있습니다.
3. 대소문자를 구분하지 않는 검색 쿼리 실행하기
이제 핵심 부분입니다. 정규 표현식 뒤에 /i 플래그를 붙이면 패턴 매칭 시 대소문자를 무시하게 됩니다. 아래 쿼리에서는 $or 연산자와 $in 연산자를 함께 사용하여, 여러 이메일 주소 중 하나라도 일치하거나 사용자 이름이 'John'인 문서를 조회합니다.
> var userMailId = [ /john@gmail.com/i, /david@gmail.com/i ]
> db.demo186.find({
... '$or': [
... { 'UserEmailId': { '$in': userMailId} },
... { 'UserName': 'John' }
... ]
...})쿼리 실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5e399d769e4f06af55199808"), "UserEmailId" : "JOHN@GMAIL.COM", "UserName" : "John" }
{ "_id" : ObjectId("5e399d979e4f06af5519980a"), "UserEmailId" : "DAVID@GMAIL.COM", "UserName" : "David" }결과 분석
흥미로운 점은 검색 조건에 소문자 john@gmail.com과 david@gmail.com을 지정했음에도 불구하고, 대문자로 저장된 JOHN@GMAIL.COM과 DAVID@GMAIL.COM 문서가 정상적으로 조회되었다는 것입니다. 이것이 바로 정규 표현식의 i(ignore case) 옵션이 하는 역할입니다.
반면 chris@gmail.com 문서는 검색 배열에 포함되지 않았기 때문에 결과에서 제외되었습니다. 참고로 두 번째 조건인 'UserName': 'John'은 문자열 정확 일치 방식이므로, 이름 필드까지 대소문자를 무시하고 검색하려면 해당 값도 /john/i 형태의 정규 표현식으로 변경하면 됩니다.
마무리
MongoDB에서 대소문자를 구분하지 않고 특정 값을 검색하는 방법을 알아보았습니다. 핵심은 정규 표현식에 i 옵션을 추가하는 것이며, 여러 조건을 조합할 때는 $or, $in 같은 논리 연산자를 함께 활용하면 됩니다. 다만 정규 표현식 기반 검색은 인덱스를 제대로 활용하지 못할 수 있으므로, 대용량 컬렉션에서 성능이 중요하다면 소문자로 정규화된 별도 필드를 저장해두고 검색하는 방식도 고려해볼 만합니다.