MongoDB in Action 5

김하영·2022년 1월 27일
0
post-custom-banner

5. 쿼리와 집계

findOne vs find 쿼리

findOne은 도큐먼트를 반환하는 반면에 find는 커서 객체를 반환한다.

  • findOne : 하나의 도큐먼트를 얻고자 한다면 도큐먼트가 존재할 경우, 그 도큐먼트를 반환한다.
    만약 매칭되는 항목이 여러 개라면 컬렉션에 존재하는 도큐먼트 중 자연 정렬상으로 가장 첫 번째 항목을 반환할 것이다.

  • find : 여러 개의 결과 도큐먼트가 필요하다면 거의 항상 find 쿼리를 사용하거나 명시적으로 결과를 정렬해야 한다.

skip, limit 그리고 쿼리 옵션

대부분의 애플리케이션에서는 리뷰를 페이지로 나누게 되는데, 이를 위해서 MongoDB는 skip과 limit 옵션을 제공한다.
이 옵션들을 이용해서 다음과 같이 리뷰 도큐먼트를 페이지로 나눌 수 있다.

db.reviews.find({'product_id': product['_id']}).skip(0).limit(12)

skip 과 limit는 질의 뒤에 호출된 것 처럼 보이지만, 정렬과 제한 매개변수는 질의와 함께 전달되고 MongoDB 서버에서 처리하게 된다. 이 구문 패턴은 메서드 체이닝(method chaining)이라 부르며, 쿼리 작성을 쉽게 하기 위한 것이다.

사용자에서의 부분 매칭 쿼리

이름(name)과 같이 다른 방식으로 사용자 컬렉션을 질의할 수도 있으며, 종종 다음에서처럼 last_name과 같은 하나의 필드로 검색할 수 있다.

db.users.find({'last_name': 'Banker'})
db.users.find({'last_name': /^Ba/})

-> "한 줄의 처음 시작에 B라 오고 그 다음에 a가 온다." 조건 검색이다.

프리픽스(prefix) 검색은 인덱스를 사용할 수 있지만 모든 정규 표현식 질의가 인덱스를 사용하는 것은 아니다.

특정 범위 질의

사용자에게 마케팅을 하는 경우에는 어떤 범위에 속하는 사용자를 대상으로 할 것이다.

db.users.find({'addresses.zip': {'$gt': 10019, '$lt': 100040}})

범위를 정의하기 위해 $gt(~보다 큰) 와 $lt(~보다 작은)를 사용할 수 있다.
이 쿼리를 효율적으로 만들기 위해서 addresses.zip 에 대해 인덱스를 정의하면 된다.

5.2 MongoDB의 쿼리 언어

5.2.1 질의조건과 셀렉터

셀렉터 매칭

가장 간단한 쿼리는 키-값 쌍이 도큐먼트에 문자적으로 일치하는 셀렉터를 사용하는 쿼리다.

db.users.find({'last_name': "Banker"})
db.users.find({'first_name': "Smith", birth_year: 1975})

MongoDB에서 모든 텍스트 문자열 일치는 대소문자를 구분한다.
대소문자를 구분하지 않는 일치를 수행해야 하는 경우 정규식 용어 사용을 고려하거나, 텍스트 검색의 사용을 살펴본다.

범위

특정 키의 값이 어떤 범위 이내에 있는 도규먼트에 대해 질의해야 할 경우가 많다.
대부분의 언어에서는 <, <=, >, >= 를 사용한다.

MongoDB 에서는 이와 비슷한 $lt, $lte, $gt, $gte 연산자를 사용한다.

  • $lt : ~ 보다 작은
  • $gt : ~ 보다 큰
  • $lte : ~ 보다 작거나 같은
  • $gte : ~ 보다 크거나 같은

집합 연산자

$in, $all, $nin 같은 세 개의 연산자는 연산자에 대한 프리디케이트(predicate)로 하나 혹은 그 이상의 값의 리스트를 받으며, 그래서 이를 집합 연산자라 부른다.

  • $in : 어떤 인수든 하나라도 참고 집합에 있는 경우 일치
  • $all : 모든 인수가 참고 집합에 있고 배열이 포함된 도큐먼트에서 사용되는 경우 일치
  • $nin : 그 어떤 인수도 참고 집합에 있지 않을 경우 일치

부울 연산자

MongoDB의 논리적 연산자로는 $ne, $not, $or, $and, $nor, $exists 가 있다.

  • $ne : 인수가 요소와 같지 않은 경우 일치
  • $not : 일치 결과를 반전시킴(반대로 만듦)
  • $or : 제공된 검색어 집합 중 하나라도 true인 경우 일치
  • $nor : 제공된 검색어 집합 중 그 어떤 것도 true가 아닌 경우 일치
  • $and : 제공된 검색어 집합이 모두 true인 경우 일치
  • $exists : 요소가 도큐먼트 안에 존재할 경우 일치

특정 키로 도큐먼트에 질의하기

$exists 연산자는 도큐먼트가 특정 키를 가지고 있는지 질의한다.

db.products.find({'details.color': {$exists: true}})

서브도큐먼트 매칭

임베디드된 객체에 대한 쿼리는 관련된 키를 .(마침표)로 구분한다.
이러한 객체 임베디드의 중첩에는 제한이 없다.

배열

도큐먼트 모델은 배열로 인해 매우 강력해진다.

  • $eleMatch : 제공된 모든 조건이 동일한 하위 도큐먼트에 있는 경우 일치
  • $size : 배열 하위 도큐먼트의 크기가 제공된 리터럴 값과 같으면 일치

자바스크립트 쿼리 연산자

쿼리에 자바스크립트 표현식을 넘겨주기 위해서는 특수한 $where 연산자를 사용할 수 있다.

  • $where : 도큐먼트를 선택하기 위해 임의의 자바스크립트를 수행한다.

정규 표현식

MongoDB는 PCRE로 컴파일되는데, 이것은 방대한 범위의 정규 표현식을 지원한다.

  • $regex : 요소를 제공된 정규 표현식과 맞춰본다.

그 밖의 쿼리 연산자

  • $mod[(몫),(결과)] : 몫으로 나눈 결과가 요소와 일치할 경우 일치
  • $type : 요소의 타입이 명시된 BSON 타입과 일치할 경우 일치
  • $text : 텍스트 인덱스로 인덱싱된 필드의 내용에 대해 텍스트 검색을 수행

5.2.2 쿼리 옵션

결괏값을 좀 더 제한하기 위해 다양한 쿼리 옵션을 사용할 수 있다.

프로젝션

프로젝션(projections)은 결괏값 도큐먼트에 대해 반환할 필드를 지정하는 데 사용한다.
특별히 도큐먼트의 수가 많을 때 프로젝션을 사용하면 네트워크 지연과 역직렬화에 들어가는 비용을 줄일 수 있다.

  • $slice : 반환되는 도큐먼트의 부분집합을 선택한다.

정렬

쿼리의 결과를 하나 혹은 그 이상의 필드에 대해 오름차순이나 내림차순으로 정렬할 수 있다.

db.reviews.find({}).sort({'rating': -1})

리뷰를 평점이 높은 것 부터 낮은 것까지 내림차순으로 정렬하였다.

profile
Back-end Developer
post-custom-banner

0개의 댓글