Computer >> 컴퓨터 >  >> 프로그래밍 >> MongoDB

MongoDB에서 정규식으로 특정 문자를 제외하고 조회하는 방법

MongoDB에서 데이터를 조회할 때 특정 문자가 포함된 문서는 제외하고 나머지 문서만 가져오고 싶은 경우가 있습니다. 이럴 때 정규식(Regular Expression)을 활용하면 간단하게 처리할 수 있으며, 크게 두 가지 방법이 있습니다.

1. 샘플 컬렉션 생성하기

먼저 실습에 사용할 컬렉션을 만들고 문서를 삽입해 보겠습니다. CustomerId 값 중 일부에는 '#' 문자가 포함되어 있습니다.

> db.regexDemo.insertOne({"CustomerId":"Customer#1234","CustomerName":"Chris"});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5cc7428f8f9e6ff3eb0ce436")
}
> db.regexDemo.insertOne({"CustomerId":"Customer5678","CustomerName":"Robert"});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5cc7429e8f9e6ff3eb0ce437")
}
> db.regexDemo.insertOne({"CustomerId":"Customer#777","CustomerName":"Carol"});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5cc742ae8f9e6ff3eb0ce438")
}
> db.regexDemo.insertOne({"CustomerId":"Customer777","CustomerName":"David"});
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5cc742bc8f9e6ff3eb0ce439")
}

2. 전체 문서 확인하기

find() 메서드를 사용해 컬렉션의 모든 문서를 출력합니다.

> db.regexDemo.find().pretty();

실행 결과는 다음과 같습니다.

{
    "_id" : ObjectId("5cc7428f8f9e6ff3eb0ce436"),
    "CustomerId" : "Customer#1234",
    "CustomerName" : "Chris"
}
{
    "_id" : ObjectId("5cc7429e8f9e6ff3eb0ce437"),
    "CustomerId" : "Customer5678",
    "CustomerName" : "Robert"
}
{
    "_id" : ObjectId("5cc742ae8f9e6ff3eb0ce438"),
    "CustomerId" : "Customer#777",
    "CustomerName" : "Carol"
}
{
    "_id" : ObjectId("5cc742bc8f9e6ff3eb0ce439"),
    "CustomerId" : "Customer777",
    "CustomerName" : "David"
}

총 4개의 문서가 저장되어 있으며, 그중 Chris와 Carol의 CustomerId에는 '#' 문자가 포함되어 있는 것을 확인할 수 있습니다.

방법 1. 문자 클래스 부정(^)을 활용한 정규식

첫 번째 방법은 정규식의 문자 클래스 부정 기호인 [^]를 사용하는 것입니다. 아래 쿼리는 CustomerId 필드 전체가 '#' 문자를 포함하지 않는 경우에만 매칭됩니다.

> db.regexDemo.find({CustomerId: /^[^#]*$/}).pretty();

실행 결과는 다음과 같습니다.

{
    "_id" : ObjectId("5cc7429e8f9e6ff3eb0ce437"),
    "CustomerId" : "Customer5678",
    "CustomerName" : "Robert"
}
{
    "_id" : ObjectId("5cc742bc8f9e6ff3eb0ce439"),
    "CustomerId" : "Customer777",
    "CustomerName" : "David"
}

'#'이 포함된 두 개의 문서(Chris, Carol)는 제외되고, 해당 문자가 없는 Robert와 David의 문서만 반환된 것을 볼 수 있습니다.

방법 2. $not 연산자와 함께 사용하기

두 번째 방법은 $not 연산자를 활용하는 것입니다. $not은 지정한 조건과 일치하지 않는 문서를 선택하므로, '#' 문자를 찾는 정규식의 결과를 뒤집어 원하는 결과를 얻을 수 있습니다.

> db.regexDemo.find({CustomerId: {$not: /#/}}).pretty();

실행 결과는 다음과 같습니다.

{
    "_id" : ObjectId("5cc7429e8f9e6ff3eb0ce437"),
    "CustomerId" : "Customer5678",
    "CustomerName" : "Robert"
}
{
    "_id" : ObjectId("5cc742bc8f9e6ff3eb0ce439"),
    "CustomerId" : "Customer777",
    "CustomerName" : "David"
}

두 방법의 차이점

두 쿼리 모두 동일한 결과를 반환하지만, 동작 방식에는 차이가 있습니다.

  • /^[^#]*$ : 문자열의 처음부터 끝까지 '#'이 아닌 문자로만 구성되어야 매칭됩니다. 필드 값이 문자열이 아닌 경우(예: null, 숫자)에는 매칭되지 않습니다.
  • {$not: /#} : '#'을 포함하는 정규식에 매칭되지 않는 모든 문서를 반환합니다. 단, 해당 필드 자체가 존재하지 않거나 정규식을 적용할 수 없는 타입인 문서도 함께 반환될 수 있다는 점에 유의해야 합니다.

따라서 실무에서는 필드의 데이터 타입과 존재 여부를 고려하여 상황에 맞는 방식을 선택하는 것이 좋습니다. 일반적으로 특정 필드가 항상 문자열로 존재한다면 어느 쪽이든 무방하며, 성능 면에서는 인덱스를 활용할 수 있는지 확인해 보는 것도 중요합니다.