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

MongoDB $group 연산에서 정렬 후 첫 번째 문서만 가져오는 방법

MongoDB의 애그리게이션 파이프라인에서 $group 연산을 사용할 때, 각 그룹 안에서 특정 기준으로 정렬된 첫 번째 문서만 추출해야 하는 경우가 자주 있습니다. 이 글에서는 $sort, $group, $project 단계를 조합해 이 작업을 수행하는 방법을 예제와 함께 살펴보겠습니다.

샘플 컬렉션 생성하기

먼저 demo576 컬렉션을 만들고 문서를 차례대로 삽입합니다.

> db.demo576.insertOne({id:101,Name:"Chris",Marks:45})
{ "acknowledged" : true, "insertedId" : ObjectId("5e916c3b581e9acd78b427fa") }
> db.demo576.insertOne({id:101,Name:"John",Marks:55})
{ "acknowledged" : true, "insertedId" : ObjectId("5e916c43581e9acd78b427fb") }
> db.demo576.insertOne({id:101,Name:"John",Marks:65})
{ "acknowledged" : true, "insertedId" : ObjectId("5e916c47581e9acd78b427fc") }
> db.demo576.insertOne({id:102,Name:"David",Marks:37})
{ "acknowledged" : true, "insertedId" : ObjectId("5e916c55581e9acd78b427fd") }
> db.demo576.insertOne({id:102,Name:"David",Marks:75})
{ "acknowledged" : true, "insertedId" : ObjectId("5e916c5e581e9acd78b427fe") }

전체 문서 조회하기

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

> db.demo576.find();

실행하면 다음과 같은 결과가 출력됩니다.

{ "_id" : ObjectId("5e916c3b581e9acd78b427fa"), "id" : 101, "Name" : "Chris", "Marks" : 45 }
{ "_id" : ObjectId("5e916c43581e9acd78b427fb"), "id" : 101, "Name" : "John", "Marks" : 55 }
{ "_id" : ObjectId("5e916c47581e9acd78b427fc"), "id" : 101, "Name" : "John", "Marks" : 65 }
{ "_id" : ObjectId("5e916c55581e9acd78b427fd"), "id" : 102, "Name" : "David", "Marks" : 37 }
{ "_id" : ObjectId("5e916c5e581e9acd78b427fe"), "id" : 102, "Name" : "David", "Marks" : 75 }

$group 연산에서 정렬 후 첫 번째 문서만 가져오기

다음은 데이터를 먼저 정렬한 뒤 $group 연산으로 각 그룹의 첫 번째 문서만 가져오는 쿼리입니다.

> var query = [
...    {
...       "$sort": { "Marks": 1 }
...    },
...    {
...       "$group": {
...          "_id": "$id",
...          "out": { "$first": "$$ROOT" }
...       }
...    },
...    {
...       "$project": {
...          "_id": "$out._id",
...          "id": "$out.id",
...          "Name": "$out.Name",
...          "MinMarks": "$out.Marks"
...       }
...    }
... ]
> db.demo576.aggregate(query);

쿼리 동작 원리

  • $sort: Marks 필드를 오름차순(1)으로 정렬해, 점수가 가장 낮은 문서가 각 그룹의 맨 앞에 오도록 만듭니다.
  • $group: id 필드를 기준으로 문서를 묶고, $first 연산자와 $$ROOT 변수를 이용해 각 그룹의 첫 번째 문서 전체를 out 필드에 담습니다.
  • $project: 최종 결과에서 _id, id, Name, 그리고 최소 점수를 의미하는 MinMarks만 선택해 깔끔하게 출력합니다.

실행 결과

애그리게이션을 실행하면 각 id 그룹별로 가장 낮은 점수를 가진 문서가 하나씩 반환됩니다.

{ "_id" : ObjectId("5e916c3b581e9acd78b427fa"), "id" : 101, "Name" : "Chris", "MinMarks" : 45 }
{ "_id" : ObjectId("5e916c55581e9acd78b427fd"), "id" : 102, "Name" : "David", "MinMarks" : 37 }

이처럼 $sort$group($first)$project 순서로 파이프라인을 구성하면 그룹별 최솟값과 함께 해당 문서의 다른 필드 정보도 한 번에 얻을 수 있습니다. 정렬 방향을 내림차순(-1)으로 바꾸면 그룹별 최댓값을 가진 문서를 손쉽게 구할 수 있으니, 분석 목적에 맞게 활용해 보시기 바랍니다.