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

MongoDB에서 $$ROOT 시스템 변수에 $first 그룹 누산기를 적용해 루트 문서 참조 반환하기

개요

누산기(Accumulator)는 애그리게이션 파이프라인을 따라 이동하는 도큐먼트들의 상태를 유지하면서 값을 집계하는 연산자입니다. 대표적인 예로 $sum, $max, $first 등이 있습니다.

$$ROOT는 시스템 변수로, 애그리게이션 파이프라인 단계에서 현재 처리 중인 루트(root) 도큐먼트, 즉 최상위(top-level) 도큐먼트 전체를 참조합니다. 이를 $first 누산기와 함께 사용하면 각 그룹에서 첫 번째로 등장한 원본 문서를 그대로 가져올 수 있습니다.

샘플 컬렉션 생성하기

먼저 도큐먼트가 포함된 컬렉션을 생성해 보겠습니다.

> db.demo582.insertOne({FirstName:"Chris",Age:21,createDate:new ISODate("2020-01-10")});{
    "acknowledged" : true, "insertedId" : ObjectId("5e91ce41fd2d90c177b5bcbd")
}
> db.demo582.insertOne({FirstName:"Chris",Age:21,createDate:new ISODate("2020-04-21")});{
    "acknowledged" : true, "insertedId" : ObjectId("5e91ce4ffd2d90c177b5bcbe")
}
> db.demo582.insertOne({FirstName:"Chris",Age:22,createDate:new ISODate("2020-02-11")});{
    "acknowledged" : true, "insertedId" : ObjectId("5e91ce59fd2d90c177b5bcbf")
}
> db.demo582.insertOne({FirstName:"Chris",Age:22,createDate:new ISODate("2020-01-12")});{
    "acknowledged" : true, "insertedId" : ObjectId("5e91ce6efd2d90c177b5bcc0")
}

저장된 도큐먼트 조회하기

find() 메서드를 사용하면 컬렉션의 모든 도큐먼트를 확인할 수 있습니다.

> db.demo582.find();

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

{ "_id" : ObjectId("5e91ce41fd2d90c177b5bcbd"), "FirstName" : "Chris", "Age" : 21, "createDate" : ISODate("2020-01-10T00:00:00Z") }
{ "_id" : ObjectId("5e91ce4ffd2d90c177b5bcbe"), "FirstName" : "Chris", "Age" : 21, "createDate" : ISODate("2020-04-21T00:00:00Z") }
{ "_id" : ObjectId("5e91ce59fd2d90c177b5bcbf"), "FirstName" : "Chris", "Age" : 22, "createDate" : ISODate("2020-02-11T00:00:00Z") }
{ "_id" : ObjectId("5e91ce6efd2d90c177b5bcc0"), "FirstName" : "Chris", "Age" : 22, "createDate" : ISODate("2020-01-12T00:00:00Z") }

$first와 $$ROOT를 활용한 그룹 쿼리 작성하기

다음은 FirstName 필드를 기준으로 그룹화하고, 그룹 누산기 연산자를 적용하는 쿼리입니다. $max로 가장 늦은 날짜를 구하고, $sum으로 문서 개수를 세며, $first$$ROOT 조합으로 그룹 내 첫 번째 원본 문서를 참조합니다.

> db.demo582.aggregate([
...     {
...        "$group": {
...           "_id": "$FirstName",
...           "MaximumDate": {
...              "$max": "$createDate"
...           },
...           "count": {
...              "$sum": 1
...           },
...           "details": {
...              "$first": "$$ROOT"
...           }
...        }
...     },
...     {
...        "$project": {
...           "MaximumDate": 1,
...           "count": 1,
...           "details": {
...              "_id": "$_id",
...              "FirstName": "$details.FirstName",
...              "Age" : "$details.Age",
...           }
...        }
...     }
... ])

실행 결과 확인하기

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

{ "_id" : "Chris", "MaximumDate" : ISODate("2020-04-21T00:00:00Z"), "count" : 4, "details" :
    { "_id" : "Chris", "FirstName" : "Chris", "Age" : 21 }
}

정리

이처럼 $first 누산기에 $$ROOT 시스템 변수를 적용하면 그룹화 과정에서 첫 번째로 처리된 루트 문서 전체를 참조할 수 있습니다. 여기에 $project 단계를 함께 사용하면 원본 문서에서 필요한 필드만 추려 깔끔한 형태의 결과를 얻을 수 있습니다. 이 기법은 그룹별 대표 문서를 추출하거나, 최신/최초 데이터와 함께 원본 정보를 유지해야 하는 경우에 매우 유용하게 활용됩니다.