[NoSQL] MongoDB MQL 학습

Yalstrax·2021년 7월 30일
3

Back End

목록 보기
6/22
post-thumbnail

MongoDB 쿼리 언어(MQL)

비교 연산자(Comparison Operators)

MongoDB의 비교 연산자는 { field : { operator : value } }와 같은 문법으로 작성하여 사용합니다.

  • 일치 여부

    • 기본적인 비교 연산자로서, Javascript의 === 또는 !==와 같은 $eq(Equal to) 와 $ne(Not equel to)가 있습니다.
  • 대소 비교

    • $gt(Greater Than)와 $lt(Less Than)로 주어진 값보다 큰 지, 작은 지를 비교할 수 있습니다.
    • $gte(Greater Than or Equal to)와 $lte(Less Than or Equal to)로는 크거나 동일한 지, 작거나 동일한 지를 비교할 수 있습니다.

db.trips.find({"tripduration":{"$lte":70},"usertype":{"$ne":"Subscriber"}})

GUI에선 find명령어 없이 사용이 가능하지만, shell에선 find명령어로 조회합니다.

tripduration이 70 이하, usertypeSubscriber가 아닌 데이터를 조회하고 있습니다.

논리 연산자(Logic Operators)

MQL(MongoDB Query Language)에는 $and, $or, $nor, 그리고 $not이라는 네 가지 논리 연산자가 있습니다.

  • $and는 지정된 모든 쿼리 절을 충족하는 도큐먼트를 반환합니다.

  • $or는 쿼리 절 중 하나라도 일치하는 도큐먼트가 있다면 해당 도큐먼트를 반환합니다.

  • $nor는 모든 절과 일치하지 않는 도큐먼트를 반환합니다.

  • 마지막으로 $not$nor의 단일 버전같이 뒤의 조건을 만족하지 않는 모든 도큐먼트를 반환합니다

$and연산자는 연산자가 지정되지 않았을 때, 기본 연산자로 사용됩니다.

Companies 컬렉션에서 total_employee가 25보다 크고 100보다 작은 회사를 $and를 이용해 쿼리한다면,

{"$and": [{ total_employee: {"$gt":25}}, {total_employee : {"$lt":100}}]}

와 같이 사용할 수 있지만, 함축할 수 있습니다.

{ total_employee: {"$gt":25}}, total_employee : {"$lt":100}}

$and를 명시하지 않는 것으로, 기본 연산자로 $and가 사용되었습니다.

이를 더 함축할 수 있습니다.

{ total_employee: {"$gt":25, "$lt":100}}

이렇게 $and를 명시하지 않고 두개의 조건을 하나로 결합하여 쿼리를 작성할 수 있습니다.

그러면 $and를 언제 명시적으로 포함해야 할까요?
일반적인 규칙으론 쿼리에 동일한 연산자를 두 번 이상 포함해야 할 때 $and를 명시합니다.

{"$and":[{"$or":[{dst_airport:"ICN"},{src_airport:"ICN"}]},{"$or":[{airplane:"CR2"},{airplane:"A81"}]}]}.count()

예를 들어, Routes 컬렉션에서 ICN을 통과하는 CR2 및 A81 비행기의 수를 확인해야 할 때 ICN을 통과하는 모든 비행기를 얻으려면 출발지 공항 또는 목적지 공항이 ICN이어야 합니다.

또한 특정 비행기 유형을 얻으려면 비행기 유형이 CR2 또는 A81이여야 한다는 조건이 필요합니다.

두 조건을 모두 충족하는 비행기의 수를 얻기위해 첫 부분에 $and를 명시적으로 추가한 다음, 두 개의 $or 조건을 배열안에 포함합니다.

요약하자면 논리 연산자를 사용하면 데이터 검색을 보다 세분화 할 수 있습니다.

논리 연산자의 구문은 $와 연산자 이름, 절로 구성된 배열입니다.

$not의 경우에는 배열이 아닌 절이 옵니다.

논리 연산자가 지정되지 않은 경우 $and가 기본 연산자로 사용되며,

동일한 연산자를 쿼리에 두 번 이상 포함해야 하는 경우, $and를 명시적으로 사용해야 합니다.

표현 연산자 (Expressive Query Operator)

  • $expr을 사용하여 쿼리 내에서 집계 표현식을 사용할 수 있습니다.
  • $expr를 사용해 변수와 조건문을 사용할 수 있습니다.
  • $expr을 사용해 같은 도큐먼트 내의 필드들을 서로 비교할 수 있습니다.

Trips 컬렉션에서 몇 명이 1200초 이상 자전거를 타고 다시 시작 지점에 자전거를 반납했는 지 $expr를 사용하여 쿼리를 작성할 수 있습니다.

먼저 $and안에 $eq$gt를 추가했습니다.

이는 우리가 비교 연산자를 사용하는 방법을 배운 것과는 약간 다릅니다.

MQL에서 비교 연산자 구문은 먼저 필드를 작성하고 나중에 적용되는 비교 연산자를 작성합니다.

그러나 이 구문은 집계 표현식을 사용합니다. 비슷해 보이지만 문법이 약간 다릅니다. 집계 구문에서는 연산자를 먼저 작성하고 그 다음 필드와 값을 작성합니다.

배열 연산자 (Array Operators)

  • $push 는 배열의 마지막 위치에 엘리먼트를 넣습니다.

    • 배열이 아닌 필드에 사용했을 경우, 필드의 타입을 배열로 바꿉니다.
  • $all 은 배열 필드에 지정한 요소가 있는 모든 도큐먼트를 반환합니다. 배열 요소의 순서와 상관없이 지정된 요소가 포함된 모든 도큐먼트를 찾을 수 있습니다.

    • 지정된 배열 필드의 배열 순서와 관계없이 지정된 모든 요소가 포함된 모든 도큐먼트들이 있는 커서를 반환합니다.
  • $size는 지정한 숫자만큼 배열의 길이를 가진 도큐먼트를 반환합니다.

    • 지정된 배열 필드가 주어진 길이와 정확히 일치하는 모든 도큐먼트들이 있는 커서를 반환합니다.

{<배열 필드> : <배열>}

배열 연산자를 쓰지않고 배열 필드를 쿼리하는 경우 배열을 지정한다면 해당 배열과 정확히 일치하는 배열을 가진 도큐먼트를 찾습니다.

{<배열 필드> : <문자열>}

문자열로 요소를 지정한다면 해당 요소가 배열에 포함된 모든 도큐먼트를 찾습니다.

도큐먼트에 너무 많은 필드와 정보가 존재하는 경우, 원하는 정보를 확인하기 어려울 때가 있습니다. 이를 find 쿼리에 Projection을 추가하는 것으로 관심있는 필드만 조회할 수 있습니다.

db.listingsAndReviews.find({
  "amenities": {"$size":20,
  "$all":["Internet","Wifi","Kitchen","Heating",...]}},
{"price":1,"address":1}).pretty()

address와 price 필드만 결과로 가져올 수 있도록 프로젝션을 추가할 수 있습니다.

find의 첫 번째 인자로 찾으려는 도큐먼트의 조건이 옵니다. 이 조건은

  • amenities 배열의 길이가 20이며, 요소로 순서 상관 없이 "Internet", "Wifi"... 를 갖고있는 배열을 찾는 조건입니다.

두 번째 인자로 찾고있는 필드를 구체적으로 설명하는 Projection이 옵니다.

이렇게 하면 결과 도큐먼트의 모든 필드를 가져올 필요가 없습니다.

위 쿼리로 실행하게되면, 조회하는 결과는 아래와 같습니다.

쿼리와 일치하는 모든 도큐먼트에 대해 해당 priceaddress를 볼 수 있습니다.

Projection을 사용할 때 결과에서 표시하거나 표시하지 않을 필드를 지정할 수 있습니다.

1을 사용하는 경우 지정한 필드와 _id 필드만 가져옵니다.

0을 사용하는 경우 지정한 필드를 제외한 모든 필드가 표시됩니다.

한번의 프로젝션에서 0과 1을 혼합 할 수 없습니다.

1과 0을 혼용할 수 있는 유일한 경우는 디폴트로 포함되는 _id 필드를 제외하도록 특별히 요청할 때입니다.

이와 같은 요청이 없다면 _id 필드가 기본적으로 도큐먼트에 포함되기 때문입니다.

$elemMatchfind 명령의 쿼리 및 프로젝션 부분에서 모두 사용할 수있는 배열 연산자입니다.

$elemMatch는 지정된 쿼리와 일치하는 요소가 하나 이상있는 배열 필드를 가지고 있는 도큐먼트를 찾을 수 있습니다.

그리고 지정된 기준과 일치하는 요소가 하나 이상있는 배열 요소만 프로젝션합니다.

profile
즐겁다면 그것만으로 만만세!

0개의 댓글