MongoDB에서는 $regex 연산자를 활용하면 대소문자를 구분하는 검색 조건을 손쉽게 설정할 수 있습니다. 특히 정규식에 i 옵션(플래그)을 추가하면 대소문자를 구분하지 않는(case-insensitive) 검색도 가능합니다.
기본 문법
가장 기본적인 정규식 검색 문법은 다음과 같습니다.
db.yourCollectionName.find({"yourFieldName" : { '$regex':'^yourValue$'}});슬래시(/) 표기법을 사용한 또 다른 방식도 있습니다. 마지막의 i 플래그가 대소문자를 무시하도록 만들어 줍니다.
db.yourCollectionName.find({"Name" : { '$regex':/^yourValue$/i}});예제 컬렉션 생성하기
개념을 이해하기 위해 샘플 문서가 포함된 컬렉션을 먼저 생성해 보겠습니다. 아래 쿼리로 컬렉션을 만들고 문서를 삽입합니다.
> db.caseInsesitiveDemo.insertOne({"Name":"John"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8bd66293c80e3f23815e83")
}
> db.caseInsesitiveDemo.insertOne({"Name":"Johnson"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8bd66693c80e3f23815e84")
}
> db.caseInsesitiveDemo.insertOne({"Name":"Johny"});
{
"acknowledged" : true,
"insertedId" : ObjectId("5c8bd66a93c80e3f23815e85")
}저장된 문서 확인하기
find() 메서드를 사용해 컬렉션의 모든 문서를 조회합니다.
> db.caseInsesitiveDemo.find().pretty();
실행 결과는 다음과 같습니다.
{ "_id" : ObjectId("5c8bd66293c80e3f23815e83"), "Name" : "John" }
{ "_id" : ObjectId("5c8bd66693c80e3f23815e84"), "Name" : "Johnson" }
{ "_id" : ObjectId("5c8bd66a93c80e3f23815e85"), "Name" : "Johny" }일반적인 정규식 검색
아래처럼 앵커(^, $) 없이 정규식을 사용하면 'John'이 포함된 모든 문서가 조회됩니다.
> db.caseInsesitiveDemo.find({"Name" : { '$regex' : 'John' }});실행 결과:
{ "_id" : ObjectId("5c8bd66293c80e3f23815e83"), "Name" : "John" }
{ "_id" : ObjectId("5c8bd66693c80e3f23815e84"), "Name" : "Johnson" }
{ "_id" : ObjectId("5c8bd66a93c80e3f23815e85"), "Name" : "Johny" }'John', 'Johnson', 'Johny' 세 개의 문서가 모두 출력되는 것을 확인할 수 있습니다. 이는 부분 일치(partial match) 검색이기 때문입니다.
Case 1: 정확히 일치하는 값만 조회하기
다른 유사한 문서들은 제외하고 정확히 일치하는 값만 조회하고 싶다면 ^(시작)와 $(끝) 앵커를 사용한 첫 번째 쿼리를 활용하세요.
> db.caseInsesitiveDemo.find({"Name" : { '$regex':'^John$'}});실행 결과:
{ "_id" : ObjectId("5c8bd66293c80e3f23815e83"), "Name" : "John" }위 출력 결과를 보면 'John'이라는 문서만 정확하게 조회된 것을 확인할 수 있습니다.
Case 2: 대소문자를 구분하지 않고 정확히 일치하는 값 조회하기
대소문자와 관계없이 정확히 일치하는 값을 찾으려면 두 번째 쿼리처럼 i 플래그를 추가하면 됩니다.
> db.caseInsesitiveDemo.find({"Name" : { '$regex':/^John$/i}});실행 결과:
{ "_id" : ObjectId("5c8bd66293c80e3f23815e83"), "Name" : "John" }이처럼 i 옵션을 사용하면 'john', 'JOHN', 'JoHn' 등 어떤 대소문자 조합으로 저장되어 있더라도 동일하게 매칭됩니다.
정리
- $regex: MongoDB에서 정규식 기반 검색을 지원하는 연산자
- ^값$: 문자열의 시작과 끝을 고정하여 정확히 일치하는 값만 매칭
- i 플래그: 대소문자를 구분하지 않는 검색을 가능하게 하는 옵션
참고로 대량의 데이터에서 자주 대소문자 무시 검색을 수행한다면, 인덱스 성능을 위해 대소문자를 구분하지 않는(collation strength 1 또는 2) 컬렉션 설정을 고려하는 것도 좋은 방법입니다.