MongoDB 연산자 중 $text에 대하여 알아봅니다.



# $text 연산자는?MongoDB를 사용하여 텍스트를 검색하는 경우 $text 연산자를 많이 사용합니다.그래서 MongoDB의 제목이나 본문 등 텍스트가 많은 경우에 원하는 텍스트를 검색할 때 매우 쉽게 검색 쿼리를 작성할 수 있도록 도와줍니다.

가장 기본적인 $text 연산자 사용의 문법입니다.

{
  $text: {
    $search: <string>,
    $language: <string>,
    $caseSensitive: <boolean>,
    $diacriticSensitive: <boolean>
  }
}



간단하게 설명하면 아래와 같습니다.

$search // 검색에 사용할 키워드 조건
$language // 검색에 사용될 언어 설정
$caseSensitive // 대소문자 구분 여부
$diacriticSensitive // 일부 언어의 발음 구분 기호 사용 여부

다음으로 MongoDB의 $text 연산자는 다음과 같은 특징이 있습니다.

- 검색어 중 포함된 검색어를 쉽게 사용
- 일치하는 Score 기준의 검색 가능
- 대소문자 구분 및 언어 설정이 가능


그럼 아래에서 자세히 알아봅니다.


! text 인덱스 설정하기
$text 연산자를 사용하는 검색시 index 설정이 반드시 필요합니다. 만약 필드명 siteName에 인덱스를 설정하는 경우 아래와 같이 사용합니다.
db.sites.createIndex({siteName: 'text'})

설정할 필드가 여러 개인 경우 아래처럼 설정할 수 있습니다. 만약 siteName, siteUrl 두 개의 필드인 경우입니다.
db.sites.createIndex({siteName: 'text', siteUrl: 'text'})

만약 해당 index를 설정하지 않으면 $text 연산자 검색시 아래의 오류가 발생할 수 있습니다.
// pymongo인 경우
pymongo.errors.OperationFailure: text index required for $text query

다음으로 웹에서 사용되는 간단한 쿼리문을 알아봅니다.


! $text 연산자 예제보기
다음은 텍스트 검색을 위하여 자주 사용할 수 있는 몇 가지 예제들입니다.


@ 'webisfree' 텍스트 찾기
db.sites.find( { $text: { $search: 'webisfree' } } )


@ 'webisfree' 또는 '웹이즈프리'를 포함한 텍스트 찾기, or 조건
db.sites.find( { $text: { $search: 'webisfree 웹이즈프리' } } )

여러개의 검색어를 찾을때는 띄어쓰기(공백)를 사용하여 가능합니다. 위의 코드는 webisfree 또는 웹이즈프리를 포함하는 경우의 검색 결과를 찾습니다.


@ 'webisfree' 그리고 '웹이즈프리'를 포함한 텍스트 찾기, and 조건
db.sites.find( { $text: { $search: '"webisfree" "웹이즈프리"' } } )

이번 예제는 위에 있는 or 조건이 아닌 and 조건... 즉 둘 다 포함된 검색어를 찾는 경우의 예제입니다. 이처럼 따옴표(quote)를 사용하여 검색할 경우 and 조건으로 포함된 검색어를 찾습니다.


@ 'webisfree' 텍스트를 찾되 'favorite'가 포함된 문서는 제외하기
db.sites.find( { $text: { $search: 'webisfree -favorite' } } )

만약 제외할 텍스트가 있는 경우 -를 사용합니다. 즉 -favorite의 경우 'favorite' 문자를 포함하지 않는 결괄르 반환합니다.


! Score에 따른 검색어 찾기
이번에는 text 검색시 score, 점수를 사용하여 찾는 경우의 방법을 알아봅니다.
db.sites.find(
  { $text: { $search: 'webisfree' } },
  { score: { $meta: 'textScore' } }
)

검색 결과 score 필드 값이 추가되어 나타나게 됩니다.


여기까지 몽고DB에서 $text 필드를 사용하는 다양한 방법을 알아보았습니다.