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

MongoDB에서 하위 문서(서브도큐먼트) 조건으로 문서를 쿼리하는 방법

개요

MongoDB에서는 $expr, $let, $arrayElemAt 같은 집계 표현식을 활용하면 배열 안에 포함된 하위 문서(서브도큐먼트)의 특정 필드 값을 조건으로 삼아 상위 문서를 조회할 수 있습니다. 이 글에서는 실제 예제를 통해 그 과정을 단계별로 살펴보겠습니다.

1단계: 컬렉션 생성 및 문서 삽입

먼저 하위 문서 배열을 포함한 컬렉션을 생성하고 문서를 삽입해 보겠습니다.

> db.demo394.insertOne(
...    {
...       details: [
...       {
...           _id: '1',
...           startDate: '2018-01-11T07:00:00.000Z',
...           endDate: '2019-01-12T07:59:59.999Z'
...       },
...       {
...           _id: '2',
...           startDate: '2019-01-21T07:00:00.000Z',
...           endDate: '2020-01-04T07:59:59.999Z'
...       }
...    ]
... }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e5e716817aa3ef9ab8ab202")
}

2단계: find() 메서드로 전체 문서 확인

find() 메서드를 사용하면 컬렉션에 저장된 모든 문서를 확인할 수 있습니다.

> db.demo394.find();

이 명령은 다음과 같은 결과를 출력합니다.

{
    "_id" : ObjectId("5e5e716817aa3ef9ab8ab202"), "details" : [
       { "_id" : "1", "startDate" : "2018-01-11T07:00:00.000Z", "endDate" : "2019-01-12T07:59:59.999Z" },
       { "_id" : "2", "startDate" : "2019-01-21T07:00:00.000Z", "endDate" : "2020-01-04T07:59:59.999Z" }
    ]
}

3단계: 하위 문서 조건으로 쿼리 실행

다음은 배열의 마지막 하위 문서에 담긴 endDate 값을 조건으로 문서를 조회하는 방법입니다.

> db.demo394.find({
...    $expr: {
...       $let: {
...          vars: { "d": { $arrayElemAt: [ "$details", -1 ] } },
...          in: { $eq: [ "$$d.endDate", "2020-01-04T07:59:59.999Z" ] }
...       }
...    }
... })

이 쿼리는 다음과 같은 결과를 반환합니다.

{
    "_id" : ObjectId("5e5e716817aa3ef9ab8ab202"), "details" : [
       { "_id" : "1", "startDate" : "2018-01-11T07:00:00.000Z", "endDate" : "2019-01-12T07:59:59.999Z" },
       { "_id" : "2", "startDate" : "2019-01-21T07:00:00.000Z", "endDate" : "2020-01-04T07:59:59.999Z" }
    ]
}

쿼리 동작 원리 살펴보기

이 쿼리가 어떻게 동작하는지 각 연산자의 역할을 정리하면 다음과 같습니다.

  • $expr: 일반 find() 쿼리 안에서 집계(aggregation) 표현식을 사용할 수 있도록 해주는 연산자입니다.
  • $let: 임시 변수를 정의하는 역할을 합니다. 여기서는 변수 d에 하위 문서 하나를 할당했습니다.
  • $arrayElemAt: 배열에서 지정한 인덱스 위치의 요소를 가져옵니다. 인덱스로 -1을 사용하면 배열의 마지막 요소를 가리킵니다.
  • $eq: 변수 d에 담긴 하위 문서의 endDate 값이 지정한 날짜 문자열과 일치하는지 비교합니다.

즉, 위 쿼리는 details 배열의 마지막 하위 문서 endDate가 '2020-01-04T07:59:59.999Z'와 일치하는 문서만 필터링하여 반환합니다. 이처럼 $expr과 함께 사용되는 집계 연산자들을 조합하면 단순 필드 매칭으로는 어려운 복잡한 조건의 쿼리도 손쉽게 작성할 수 있습니다.